Red*_*Red 5 python metaprogramming metaclass
在使用元类崩溃之后,我深入研究了Python中元编程的主题,我有几个问题,即imho,在可用的文档中没有明确的答案.
__new__,并__init__在元类,它们的参数必须定义相同?__init__在元类中定义类的最有效方法是什么?对于 1:任何类的__init__和都必须接受相同的参数,因为它们将使用相同的参数进行调用。通常采用更多它忽略的参数(例如,采用任何参数并忽略它们),以便在继承过程中不必覆盖它们,但通常只有在根本没有参数时才这样做。__new____new__object.__new____new____new__
这在这里不是问题,因为正如前面所说,元类总是使用相同的参数集来调用,因此您不会遇到麻烦。至少有论据。但是,如果您要修改传递给父类的参数,则需要同时修改它们。
对于 2:您通常不在__init__元类中定义该类。您可以编写一个包装器并替换元类__init__中的类的,也可以在元类上重新定义 。如果您使用继承,前者会表现得很奇怪。__new____init____call__
import functools
class A(type):
def __call__(cls, *args, **kwargs):
r = super(A, cls).__call__(*args, **kwargs)
print "%s was instantiated" % (cls.__name__, )
print "the new instance is %r" % (r, )
return r
class B(type):
def __init__(cls, name, bases, dct):
super(B, cls).__init__(name, bases, dct)
if '__init__' not in dct:
return
old_init = dct['__init__']
@functools.wraps(old_init)
def __init__(self, *args, **kwargs):
old_init(self, *args, **kwargs)
print "%s (%s) was instantiated" % (type(self).__name__, cls.__name__)
print "the new instance is %r" % (self, )
cls.__init__ = __init__
class T1:
__metaclass__ = A
class T2:
__metaclass__ = B
def __init__(self):
pass
class T3(T2):
def __init__(self):
super(T3, self).__init__()
Run Code Online (Sandbox Code Playgroud)
调用它的结果:
>>> T1()
T1 was instantiated
the new instance is <__main__.T1 object at 0x7f502c104290>
<__main__.T1 object at 0x7f502c104290>
>>> T2()
T2 (T2) was instantiated
the new instance is <__main__.T2 object at 0x7f502c0f7ed0>
<__main__.T2 object at 0x7f502c0f7ed0>
>>> T3()
T3 (T2) was instantiated
the new instance is <__main__.T3 object at 0x7f502c104290>
T3 (T3) was instantiated
the new instance is <__main__.T3 object at 0x7f502c104290>
<__main__.T3 object at 0x7f502c104290>
Run Code Online (Sandbox Code Playgroud)
对于 3:是的,__call__如上所示。