Для 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__()
И результат его вызова:
>>> 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>
Для 3: Да, с __call__
, как показано выше.