2015-02-01 6 views
2

В Python3 я могу сделать (благодаря pep 3102):предотвратить опечатки в переменной ключевого слова арг

def some_fun(a, *args, log=None, verbose=0): 
    pass 

и быть уверенным, что если я называю это с:

some_fun(1, 2, 3, lob=debug_log) 

я получаю ошибку типа на неожиданный аргумент ключевого слова lob.

На Python2 Я не могу определить some_fun() с аргументами только для ключевого слова после списка произвольных аргументов. Я должен сделать:

def some_fun(a, *args, **kw): 
    log = kw.get("log", None) 
    verbose = kw.get("verbose", 0) 

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

ответ

2

Вместо того, чтобы использовать .get() для извлечения значений, используйте .pop() и проверьте, пуст ли kw после появления всех аргументов только для ключевого слова.

Я использую небольшую вспомогательную функцию для этого:

def check_empty_kwargs(kwargs): 
    import inspect 
    try: 
     keys = kwargs.keys() 
     assert len(keys) == 0 
    except AssertionError: 
     # uncomment if you want only one of the unexpected kwargs in the msg 
     # keys = keys[:1] 
     msg = "{0}() got an unexpected keyword argument{1} {2}".format(
     inspect.stack()[1][3], # caller name 
     's' if len(keys) > 1 else '', 
     ', '.join(["'{0}'".format(k) for k in keys])) 
     raise TypeError(msg) 

И вы бы использовать его как:

def some_fun(a, *args, **kw): 
    log = kw.pop("log", None) 
    verbose = kw.pop("verbose", 0) 
    check_empty_kwargs(kw) 

вызова, что с (при условии debug_log определен)

some_fun(1, 2, 3, lob=debug_log) 
.... 
TypeError: some_fun() got an unexpected keyword argument 'lob' 

Отслеживание будет (конечно) отличаться от Python3

1

Вы можете проверить против разрешенных ключей, например:

def f(a, *args, **kwargs): 
    surplus = set(kwargs).difference(('log', 'foo', 'bar')) 
    if surplus: 
     raise TypeError('got unexpected keyword argument(s): ' + ', '.join(surplus)) 
+0

Выглядит хорошо, но это только работает в 2.7+ – Snake

+0

@Snake изменился, чтобы быть немного более гибкой версией ... –

+0

Это работает. Я постараюсь повысить это, как только у меня хватит репутации. – Snake

1

Если у вас есть несколько этапов обработки, вы можете комбинировать вышеперечисленные методы с другой:

def f(a, *args, **kwargs): 
    # we allow xyz, a, b 
    xyz = kwargs.pop('xyz', 1) 
    # now xyz must be gone, so we can only have a and/or b 
    others = (lambda a=1, b=2: (a, b)(**kwargs)) 
    # either that was ok or it failed 
    return xyz, others