python中type和type.__new__有什么区别?
我在写一个元类的时候,不小心写成了这样:
class MetaCls(type):
def __new__(cls, name, bases, dict):
return type(name, bases, dict)
...而不是像这样:
class MetaCls(type):
def __new__(cls, name, bases, dict):
return type.__new__(cls, name, bases, dict)
这两个元类到底有什么区别呢?更具体一点,为什么第一个元类不能正常工作(有些类没有被这个元类调用)?
6 个回答
首先,你需要了解一下 object.__new__()
是怎么工作的。
下面是来自官方文档的解释:
object.__new__(cls[, ...])
这个方法是用来创建一个类
cls
的新实例的。__new__()
是一个静态方法(特别处理过,所以你不需要特别声明它),它的第一个参数是你想要创建实例的类。后面的参数是传给对象构造函数的(也就是调用类时传的参数)。__new__()
的返回值应该是新创建的对象实例(通常是cls
的一个实例)。一般来说,创建新实例的实现方式是调用父类的
__new__()
方法,使用super(currentclass, cls).__new__(cls[, ...])
,并传入合适的参数,然后在返回之前对新创建的实例进行必要的修改。如果
__new__()
返回的是cls
的一个实例,那么新实例的__init__()
方法会被调用,像这样__init__(self[, ...])
,其中self
是新实例,剩下的参数和传给__new__()
的参数是一样的。如果
__new__()
没有返回cls
的实例,那么新实例的__init__()
方法就不会被调用。
__new__()
主要是为了让不可变类型(比如int
、str
或tuple
)的子类可以自定义实例的创建。它也常常在自定义元类中被重写,以便自定义类的创建。
所以在 mg. 的回答中,前者没有调用 __init__
函数,而后者在调用 __new__
后调用了 __init__
函数。
请参考下面的注释,希望对你有帮助。
class MetaCls(type):
def __new__(cls, name, bases, dict):
# return a new type named "name",this type has nothing
# to do with MetaCls,and MetaCl.__init__ won't be invoked
return type(name, bases, dict)
class MetaCls(type):
def __new__(cls, name, bases, dict):
# return a new type named "name",the returned type
# is an instance of cls,and cls here is "MetaCls", so
# the next step can invoke MetaCls.__init__
return type.__new__(cls, name, bases, dict)
在第一个例子中,你是在创建一个全新的类:
>>> class MetaA(type):
... def __new__(cls, name, bases, dct):
... print 'MetaA.__new__'
... return type(name, bases, dct)
... def __init__(cls, name, bases, dct):
... print 'MetaA.__init__'
...
>>> class A(object):
... __metaclass__ = MetaA
...
MetaA.__new__
>>>
而在第二个例子中,你是在调用父类的 __new__
方法:
>>> class MetaA(type):
... def __new__(cls, name, bases, dct):
... print 'MetaA.__new__'
... return type.__new__(cls, name, bases, dct)
... def __init__(cls, name, bases, dct):
... print 'MetaA.__init__'
...
>>> class A(object):
... __metaclass__ = MetaA
...
MetaA.__new__
MetaA.__init__
>>>