Есть ли способ вызвать функцию Python с неправильным количеством аргументов, не вызывая TypeError? - PullRequest
1 голос
/ 01 июня 2009

Когда вы вызываете функцию с неправильным числом аргументов или с аргументом ключевого слова, которого нет в ее определении, вы получаете TypeError. Я хотел бы, чтобы кусок кода принял обратный вызов и вызвал его с переменными аргументами, основываясь на том, что поддерживает обратный вызов. Один из способов сделать это для обратного вызова cb - использовать cb.__code__.cb_argcount и cb.__code__.co_varnames, но я бы предпочел абстрагировать это во что-то вроде apply, но при этом применяются только те аргументы, которые "подходят".

Например:

 def foo(x,y,z):
   pass

 cleanvoke(foo, 1)         # should call foo(1, None, None)
 cleanvoke(foo, y=2)       # should call foo(None, 2, None)
 cleanvoke(foo, 1,2,3,4,5) # should call foo(1, 2, 3)
                           # etc.

Есть ли что-то подобное в Python или я должен написать с нуля?

Ответы [ 2 ]

7 голосов
/ 01 июня 2009

Вместо того, чтобы копаться в деталях самостоятельно, вы можете проверить подпись функции - вы, вероятно, захотите inspect.getargspec(cb).

Точно, как вы хотите использовать эту информацию, и ваши аргументы, чтобы вызвать функцию «правильно», мне не совсем понятно. Предполагая для простоты, что вы заботитесь только о простых именованных аргументах, и значения, которые вы хотите передать, находятся в dict d ...

args = inspect.getargspec(cb)[0]
cb( **dict((a,d.get(a)) for a in args) )

Может быть, вы хотите что-то более изумительное и можете уточнить, что именно?

3 голосов
/ 01 июня 2009

Это может быть?

def fnVariableArgLength(*args, **kwargs):
    """
    - args is a list of non keywords arguments
    - kwargs is a dict of keywords arguments (keyword, arg) pairs
    """
    print args, kwargs


fnVariableArgLength() # () {}
fnVariableArgLength(1, 2, 3) # (1, 2, 3) {}
fnVariableArgLength(foo='bar') # () {'foo': 'bar'}
fnVariableArgLength(1, 2, 3, foo='bar') # (1, 2, 3) {'foo': 'bar'}

Редактировать Ваши варианты использования

def foo(*args,*kw):
    x= kw.get('x',None if len(args) < 1 else args[0])
    y= kw.get('y',None if len(args) < 2 else args[1])
    z= kw.get('z',None if len(args) < 3 else args[2])
    # the rest of foo

foo(1)         # should call foo(1, None, None)
foo(y=2)       # should call foo(None, 2, None)
foo(1,2,3,4,5) # should call foo(1, 2, 3)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...