限制函数/方法的可选,位置参数的数量

时间:2009-11-11 22:15:38

标签: python

什么是限制函数或方法的可选位置参数数量的适当解决方案?例如。我想要一个带有两个或三个位置参数的函数(但不是更多)。我不能使用可选的关键字参数(因为该函数需要接受无限数量的任意命名的关键字参数)。到目前为止我想出的是这样的:

def foo(x, y, *args, **kwargs):
    if len(args) == 1:
        # do something
    elif len(args) > 1:
        raise TypeError, "foo expected at most 3 arguments, got %d" % (len(args) + 2)
    else
        # do something else

这是合理的还是有更好的方法?

6 个答案:

答案 0 :(得分:2)

这有效:

>>> def foo(a, b, c=3, **kwargs):
    print(a, b, c, kwargs)


>>> foo(3, 4, 2)
3 4 2 {}
>>> foo(3, 4)
3 4 3 {}

答案 1 :(得分:2)

找出什么是“pythonic”的一种方法是在python源代码本身中搜索示例。

find '/usr/lib/python2.6' -name '*.py' -exec egrep 'len\(args\)' {} + | wc
    156     867   12946

如果你仔细阅读上述命令的结果(没有wc),你会发现很多例子都使用你提出的技术。

答案 2 :(得分:1)

你的解决方案对我来说似乎很合理。

答案 3 :(得分:1)

你可以写一个装饰者:

class TooManyArgumentsException(Exception):
    pass

def limit_args(n):
    def limit_decorator(f):
        def new_f(*args, **kwargs):
            if len(args) > n:
                raise TooManyArgumentsException("%d args accepted at most, %d args passed" % (n, len(args)))
            return f(*args, **kwargs)
        return new_f
    return limit_decorator

然后像这样使用它:

>>> @limit_args(5)
... def f(a, b, *args):
...     return a + b + sum(args)
...
>>> f(1, 2, 3)
6
>>> f(1, 2, 3, 4)
10
>>> f(1, 2, 3, 4, 5)
15
>>> f(1, 2, 3, 4, 5, 6)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "limit.py", line 8, in new_f
    raise TooManyArgumentsException("%d args accepted at most, %d args passed" % (n, len(args)))
limit.TooManyArgumentsException: 5 args accepted at most, 6 args passed
>>> 

答案 4 :(得分:0)

对我来说很好看。

如果你想从函数体中抽象出那个逻辑,可以将它放在装饰器中:

def validate_num_args(num_args=None, num_kwargs=None):
    def entangle(f):
        def inner(*args, **kwargs):
            if not num_args is None and len(args) > num_args:
                raise ValueError("Too many arguments, got %s, wanted %s." % (len(args), num_args))
            if not num_kwargs is None and len(kwargs) > num_kwargs:
                raise ValueError("Too many keyword arguments, got %s, wanted %s." % (len(kwargs), num_kwargs))
            return f(*args, **kwargs)
        return inner
    return entangle

@validate_num_args(num_args=3)
def foo(x, y, *args, **kwargs):
    return "do something with these variables:", x, y, args, kwargs

print "Good:\n", foo(1,2,3)
print ""
print "Bad:\n", foo(1,2,3,4)

此代码的输出为:

Good:
('do something with these variables:', 1, 2, (3,), {})

Bad:
Traceback (most recent call last):
  File "c:\so.py", line 18, in <module>
    print "Bad:\n", foo(1,2,3,4)
  File "c:\so.py", line 5, in inner
    raise ValueError("Too many arguments, got %s, wanted %s." % (num_args, len(args)))
ValueError: Too many arguments, got 4, wanted 3.

答案 5 :(得分:0)

我迟到了吗?我这样做:

def (positional_1, positional_2, *, keyword_arguments...):

检查PEP 3102 -- Keyword-Only Arguments以获得更多参考。