问题
如何在python中按程序创建一个函数,该函数接受特定的命名参数,但允许这些参数名称是数据驱动的?
例子
比如,你想创建一个类装饰器,
with_init
,这将添加
__init__
具有特定命名参数的方法,以便以下两个类是等效的。
class C1(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
@with_init('x y z')
class C2(object):
pass
我的第一次尝试是做一个接受
*args
而不是特定的命名参数:
class with_init(object):
def __init__(self, params):
self.params = params.split()
def __call__(self, cls):
def init(cls_self, *args):
for param, value in zip(self.params, args):
setattr(cls_self, param, value)
cls.__init__ = init
return cls
它在某些情况下工作:
>>> C1(1,2,3)
<__main__.C1 object at 0x100c410>
>>> C2(1,2,3)
<__main__.C2 object at 0x100ca70>
但在其他人身上就没那么多了:
>>> C2(1,2,3,4) # Should fail, but doesn't.
<__main__.C2 object at 0x100cc90>
>>> C2(x=1, y=2, z=3) # Should succeed, but doesn't.
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
TypeError: init() got an unexpected keyword argument 'y'
当然,我可以将代码添加到嵌套
init
函数尝试检查每个可能的情况,但似乎应该有一个更简单的方法。
我注意到了
collections.namedtuple
通过将字符串传递给
exec
. 在我看来,这似乎很圆,但也许这就是解决办法。
什么是正确的执行
with_init.__call__
?
注意:我想要一个Python2.x解决方案。