2015-01-21 3 views
0

Я думал о прикреплении словаря к локальному пространству как-то, однако я видел похожие вопросы, заданные на SO - обычно с ответом «не делай этого!». Я проиллюстрирую свою проблему и приветствую любые предложения по ее преодолению.Python удобная передача аргументов слова для функции

Если у вас есть словарь параметров (читайте у JSON, поэтому предпочитайте, чтобы вам не приходилось возиться с ним), и я решил передать это следующим образом;

def testParse(dataObj, userOptions): 

    # Merge default with passed options taking prescidence 
    defaultOpts = { 

     'boxheight' : 200, 
     'boxwidth' : 100, 
     'padding' : 150 

    } 
    opt = dict(userOptions.items() | defaultOpts.items()) 

Вопрос в том, Есть ли способ, чтобы прикрепить каждое значение в словаре локальной области видимости с помощью ключа так, что вместо выписывал весь словарь

boxheight = opt['boxheight'] 

и т.д., или писать opt['boxheight'] каждый раз, когда я обращаюсь к нему. Можно ли просто закодировать словарь opt и присвоить значение программно?

Я никоим образом не привязан к описанному подходу, но все варианты будут использоваться в локальных выражениях в какой-то момент, и они существуют с самого начала в качестве словаря. Большое спасибо заранее за ваши предложения.

[Отказ от ответственности: только работает с Python в течение нескольких дней]

+0

Нет, для локальных переменных нет способа сделать это. Сколько предметов есть в dicitonary? Я предлагаю явные задания. –

+3

Самый простой способ справиться с этим - использовать аргументы ключевого слова для подфункций, а затем просто распаковать словарь в вызов (например, 'def func (padding, ** kwargs)' then' func (** opt) 'будет делать' padding', доступный локально в 'func', и упаковывает все остальное в' kwargs'). – jonrsharpe

+0

@jonrsharpe - красивый! – Joe

ответ

0

Ok, спасибо @ jonrshapre Замечаний у меня есть следующее решение

# user options 
userOps = { 'name' : 'joe', 'age' : 21 } 
data = (1,2) 

# default options specified as function argument 
def _func(data, name, lovesSO = True, **kwargs): 

    print(data) 
    print(name) 
    print(lovesSO) 
    print(kwargs) 

# Call 
_func(data, **userOps)  

# OUTPUTS 
# (1,2) 
# joe 
# True 
# {'age' : 21} 

расплаты с таким подходом, как представляется, слегка нетрадиционный синтаксис вызова (хотя, как указано в комментариях, это необычно для новичка, подобного мне). Однако это можно устранить путем определения

def func(data, options): _func(data, **options) 

Или другое решение на основе комментария @ Sven Marnach;

# Utility options class 
class Options: 
    def __init__(self, defaults, user_opts): 
     vars(self).update(defaults) 
     vars(self).update(user_opts) 

def func2(data, userOps): 

    opt = Options({ 'lovesSO' : True}, userOps) 

    print(data) 
    print(opt.name) 
    print(opt.lovesSO) 

# Call  
func2(data, userOps) 

# OUTPUT 
# (1, 2) 
# joe 
# True 

Это имеет недостаток, заключающийся в определении вспомогательного класса, но имеет преимущество четко знать, какие переменные определяемые пользователем опции наличием префикса opt.. Кроме того, вызывающий синтаксис является естественным.

В обоих случаях неиспользуемые пользовательские параметры сохраняются либо как словарь kwargs (в первом случае), либо как неиспользуемые записи в словаре opt.

Лично я решил выбрать второе решение.

+1

* «слегка нетрадиционный синтаксис вызова» * кажется неточным - '*' и '**' широко используются в идиоматическом Python. Обратите также внимание на то, что они будут использоваться по-разному - с помощью Sven вы передадите единый объект «пространства имен» ** на «func2», содержащий все пользовательские параметры, вместо того, чтобы создавать «пространство имен» внутри * функции , – jonrsharpe

+0

спасибо @jonrsharpe, сейчас обновится. – Joe

+0

@jonrsharpe. Re: Свенский подход; Если я определяю объект Namespace вне func2, то параметры по умолчанию будут перезаписывать параметры пользователя no? Казалось бы, тогда мне нужно будет сделать какую-то проверку ключа? – Joe

Смежные вопросы