6

有没有办法获取传递给函数的实际参数的数量

def foo(a, optional=42):
    if ????
        print "1 arg"
    else:
        print "2 args"

foo(11)      # should print 1 arg
foo(22, 42)  # should print 2 args

不改变其签名接受*args

4

3 回答 3

6

您可以将默认值更改为哨兵:

_sentinel = object()

def foo(a, optional=_sentinel):
    if optional is _sentinel:
        optional = 42
        print "1 arg"
    else:
        print "2 args"

或者直接在func_defaults元组中访问它:

def foo(a, optional=object()):
    if optional is foo.func_defaults[0]:
        optional = 42
        print "1 arg"
    else:
        print "2 args"

但实际上不要使用它;这只会使那些不熟悉标准函数对象属性的人感到困惑。

是的,该_sentinel对象是可自省的,并且仍然可以由坚定的开发人员获得,但是同样的开发人员也可以对您的功能进行猴子补丁。:-)

于 2013-10-25T12:35:08.073 回答
6

你可以使用装饰器来做到这一点。从保留装饰函数的签名问题中,我们知道如何正确执行此操作。

import decorator


@decorator.decorator
def count_args(f):
    def new(*args, **kwargs):
        kwargs['nargs'] = len(args)+len(kwargs)
        return f(*args, **kwargs)
    return new

@count_args
def foo(a, optional=42, nargs=1):
    print nargs

foo(1) # 1
foo(1, 4) # 2
foo(1, optional=4) # 2

更新:

我刚刚为我们传递给函数的 args 数量添加了关键字参数。如您所见,默认情况下为 1,即 True。这看起来像一个黑客,但它有效。

于 2013-10-25T12:41:01.457 回答
0

我会使用装饰器:

def wrapper(func):
    def wrapped(*args):
        if len(args) == 2:
            print "2 arg"
        else:
            print "1 arg"
    return wrapped

@wrapper
def foo(a,optional=None):
    pass

foo(11)
#1 arg

foo(22, 42)
#2 arg
于 2013-10-25T13:12:56.760 回答