Python 的抽象使用导致 TypeError
Abstract uses of Python result in TypeError
以下面的代码为例:
def inner(a, b):
return (a, b)
def outer(func, *args, **kwargs):
return func(*args, **kwargs)
当执行 outer(inner, 1, b=2)
时 returns 正确的值 (1, 2)
.
如何使用作为 kwargs
传递的参数 a
和作为 arg
传递的参数 b
调用同一个函数?即:outer(inner, 1, a=2)
。
运行 outer(inner, 1, a=2)
引发异常:TypeError: inner() got multiple values for argument 'a'
.
如何包装函数以便传递参数"out of order"?
您可以inspect
方法并获取参数名称。然后,您生成所有显式传递的其余参数的列表。喜欢:
>>> list(inspect.signature(inner).parameters)
['a', 'b']
因此您可以生成剩余参数列表:
import inspect
def outer(func, *args, **kwargs):
remain = list(par for par in inspect.signature(func).parameters if par not in kwargs)
kwargs.update(zip(remain,args))
return func(**kwargs)
所以它将忽略所有显式声明的变量,然后zip
剩余的未命名变量(此处剩下的一个是 b
) 和 未命名的值 .
请注意,如果您这样指定
def inner3(a,b,c):
return (a,b,c)
如果您指定 outer(inner,1,2,a=4)
,则需要将未命名变量指定为 (b,c)
(该顺序),因此 b = 1
和 c = 2
。如果您指定 outer(inner,1,2,b=4)
,则 a = 1
和 c = 2
。此外,如果您指定两个参数,此处未命名的参数将与其余参数统一,因此 outer(inner,1,a=2,c=4)
将导致 b=1
.
话虽这么说,但我认为不是一个好主意。这种行为很难理解,所以人们往往会犯错误。 Python 的设计者没有选择在解释器级别支持此功能可能有充分的理由。当然,您可能有(很好的)理由想要这样做,但在这样做之前请三思。
以下面的代码为例:
def inner(a, b):
return (a, b)
def outer(func, *args, **kwargs):
return func(*args, **kwargs)
当执行 outer(inner, 1, b=2)
时 returns 正确的值 (1, 2)
.
如何使用作为 kwargs
传递的参数 a
和作为 arg
传递的参数 b
调用同一个函数?即:outer(inner, 1, a=2)
。
运行 outer(inner, 1, a=2)
引发异常:TypeError: inner() got multiple values for argument 'a'
.
如何包装函数以便传递参数"out of order"?
您可以inspect
方法并获取参数名称。然后,您生成所有显式传递的其余参数的列表。喜欢:
>>> list(inspect.signature(inner).parameters)
['a', 'b']
因此您可以生成剩余参数列表:
import inspect
def outer(func, *args, **kwargs):
remain = list(par for par in inspect.signature(func).parameters if par not in kwargs)
kwargs.update(zip(remain,args))
return func(**kwargs)
所以它将忽略所有显式声明的变量,然后zip
剩余的未命名变量(此处剩下的一个是 b
) 和 未命名的值 .
请注意,如果您这样指定
def inner3(a,b,c):
return (a,b,c)
如果您指定 outer(inner,1,2,a=4)
,则需要将未命名变量指定为 (b,c)
(该顺序),因此 b = 1
和 c = 2
。如果您指定 outer(inner,1,2,b=4)
,则 a = 1
和 c = 2
。此外,如果您指定两个参数,此处未命名的参数将与其余参数统一,因此 outer(inner,1,a=2,c=4)
将导致 b=1
.
话虽这么说,但我认为不是一个好主意。这种行为很难理解,所以人们往往会犯错误。 Python 的设计者没有选择在解释器级别支持此功能可能有充分的理由。当然,您可能有(很好的)理由想要这样做,但在这样做之前请三思。