![](/img/trans.png)
[英]SyntaxError using *args and **kwargs in an __init__ in Python
[英]python create a metaclass which auto __init__ for *args and **kwargs
当我创建一个 python 类并在init方法中我只写:
self.name1 = name1
self.name2 = name2
....
对于所有参数。
那么,如何优雅地为不同的*args
和**kwargs
编写__init__
?
我想编写一个元类来自动设置*args
和**kwargs
属性:
#the metaclass to be used
class LazyInit():
# code here
然后当我创建它的子类时,子类将自动__init__
为他们自己的*args
和**kwargs
。
class Hospital(metaclass = LazyInit):
def __init__(self, *args,**kwargs): pass
class Basketball(metaclass = LazyInit):
def __init__(self, *args, **kwargs): pass
a = 1
b = 2
c = 3
a_hospital = Hospital(a, b, kw1 =1, kw2 =2)
a_circle = Basketball(a, c, kw3 = 10, kw4 = 20)
我只知道我们只能使用setattr
来为**kwargs
做这件事:
class LazyInit():
def __init__(self,**kwargs):
for k,v in kwargs.items():
setattr(self,k,v)
LazyInit(a=1).a
1
但是,这不是可以在子类中使用的元类。 我应该在我的每个子类中编写此代码片段...
首先,制作一个装饰器来进行绑定。
from functools import wraps
from inspect import signature
def binds(f):
@wraps(f)
def __init__(self, *args, **kwargs):
# Update self attributes with inspected binding of arg names to values.
vars(self).update(signature(f).bind(None, *args, **kwargs).arguments)
# `self` is also an arg, but we didn't really want to save this one.
del self.self
return __init__
这是您可以使用它的方法。
class Foo:
@binds
def __init__(self, foo, bar, *args, baz, **kwargs):
pass
还有一个演示:
>>> vars(Foo(1,2,3,4,baz=5,quux=10))
{'foo': 1, 'bar': 2, 'args': (3, 4), 'baz': 5, 'kwargs': {'quux': 10}}
现在剩下的就是让元类自动应用这个装饰器。
class AutoInit(type):
def __new__(cls, name, bases, namespace):
namespace['__init__'] = store_args(namespace['__init__'])
return type.__new__(cls, name, bases, namespace)
AutoInit
是默认元类type
的子类。 在构建时,它会找到 init 方法并将其替换为包装版本。 type
处理其余部分。
现在您可以像使用任何其他元类一样使用它:
class Bar(metaclass=AutoInit):
def __init__(self, spam, eggs, *, bacon):
pass
示范:
>>> vars(Bar(1,2,bacon=3))
{'spam': 1, 'eggs': 2, 'bacon': 3}
而且这种行为也会被继承。
class Baz(Bar):
def __init__(self, spam, eggs, sausage, *, bacon):
super().__init__(spam, eggs, bacon=bacon)
演示(注意'sausage'
):
>>> vars(Baz(1,2,3,bacon=4))
{'spam': 1, 'eggs': 2, 'sausage': 3, 'bacon': 4}
元类是深奥的魔法。 很强大,但是很模糊。 你几乎从不需要它们(如果你不确定,假设你不需要)。 过多使用元类的代码会变得非常难以理解和维护。
在这种情况下,您可能应该在装饰器处停下来。 它几乎可以完成您想要的一切,而不会那么混乱。 显式优于隐式。 代码读的比写的多。 可读性很重要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.