什么是限制函数或方法的可选位置参数数量的适当解决方案?例如。我想要一个带有两个或三个位置参数的函数(但不是更多)。我不能使用可选的关键字参数(因为该函数需要接受无限数量的任意命名的关键字参数)。到目前为止我想出的是这样的:
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
这是合理的还是有更好的方法?
答案 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以获得更多参考。