実際、いくつかの違いがあります。
一つには、との最初の引数は同じではありません。これは、を使用しているすべての人に役立つわけではありませ__new__
ん。誰かがこれを指摘しました、そしてそれは違いを理解するための核心です: __init__
cls
__new__
メタクラスを取得します-MyType
私の例では(アプリケーションレベルのクラスはまだ作成されていないことを思い出してください)。ここで変更できますbases
(注意しないと、MRO解決エラーが発生する可能性があります)。
__init__
新しく作成されたアプリケーションレベルのクラスを取得Bar
しFoo
、その時点で、このクラスの名前空間が設定されていcls_attrib
ます。以下の例を参照してください。
サンプルコード:
class Mixin:
pass
class MyType(type):
def __new__(mcls, name, bases, attrs, **kwargs):
print(" MyType.__new__.mcls:%s" % (mcls))
if not Mixin in bases:
#could cause MRO resolution issues, but if you want to alter the bases
#do it here
bases += (Mixin,)
#The call to super.__new__ can also modify behavior:
# classes Foo and Bar are instances of MyType
return super(MyType, mcls).__new__(mcls, name, bases, attrs)
#now we're back to the standard `type`
#doing this will neuter most of the metaclass behavior, __init__ wont
#be called.
#return super(MyType, mcls).__new__(type, name, bases, attrs)
def __init__(cls, name, bases, attrs):
print(" MyType.__init__.cls:%s." % (cls))
#I can see attributes on Foo and Bar's namespaces
print(" %s.cls_attrib:%s" % (cls.__name__, getattr(cls, "cls_attrib", None)))
return super().__init__(name, bases, attrs)
print("\n Foo class creation:")
class Foo(metaclass=MyType):
pass
print("\n bar class creation:")
class Bar(Foo):
#MyType.__init__ will see this on Bar's namespace
cls_attrib = "some class attribute"
出力:
Foo class creation:
MyType.__new__.mcls:<class '__main__.test.<locals>.MyType'>
MyType.__init__.cls:<class '__main__.test.<locals>.Foo'>.
Foo.cls_attrib:None
Bar class creation:
MyType.__new__.mcls:<class '__main__.test.<locals>.MyType'>
MyType.__init__.cls:<class '__main__.test.<locals>.Bar'>.
Bar.cls_attrib:some class attribute