严格地说,创建实例的不是A.__new__()。
当您定义class A(object):(或者class A:,如果您使用Python3,class A:是old-style class that has been deprecated)时,它是__new__来自被调用来创建实例a的继承object.__new__()。
当执行a = A()时,将发生以下情况:A()是A.__call__的简写
object.__new__(cls, *args, **kwargs)其中cls=A,是在hood下实际发生的创建实例a。它为新对象分配内存,应该然后返回一个新对象(实例)。
如果且仅当返回新创建的对象时,__init__(self)才调用新创建的对象来“初始化”该对象。
考虑以下演示:当我们重写__new__并且不再返回对象时,__init__将
不被呼叫:class A(object):
def __new__(cls, *args, **kwargs):
print cls, args, kwargs
def __init__(self):
self.x = 'init!'
print self.x
In : a = A()
() {}
# note that "init!" has not appeared here because __new__ didn't return an
# new instance
现在,使用object.__new__返回一个新实例,您将看到
在__new__之后,也将调用__init__:class A(object):
def __new__(cls, *args, **kwargs):
print cls, args, kwargs
return object.__new__(cls, args, kwargs)
def __init__(self):
self.x = 'init!'
print self.x
In : a = A()
() {}
init!
下面是另一个演示来显示差异,请注意,可以在不调用__init__()的情况下创建实例a:class A(object):
def __init__(self):
self.x = "init!"
print self.x
In : a = object.__new__(A)
In : a
Out: <__main__.a at>
In : a.__dict__
Out: {}
In : aa = A()
init!
In : aa
Out: <__main__.a at>
In : aa.__dict__
Out: {'x': 'init!'}
现在对于好奇的人(也为了刷新我自己的记忆=):
粗略地说,在Python中创建新对象的方法主要有两种:
通过子类化创建新对象(type/class)
class语句告诉Python创建一个新的类型/类对象(通过
子类化现有的类型/类例如object):class Hello(object):
pass
>>> Hello.__class__
实际上,所有类/类型对象都有类型type。类型type
(type(type))仍然是类型。
您可以子类化一个类型/类对象。
通过实例化创建新对象(实例):
还可以通过设置现有的类型对象来创建新对象。
这是通过使用__call__运算符(缩写为())完成的:>>> h = hello()
>>> type(h)
>>> type(int('1'))
不能对实例对象进行子类划分。
(注意,您还可以通过其他方法创建一个新的实例对象,例如
正如使用列表运算符[1,2,3],在本例中,它创建一个列表实例)
可以通过type(my_obj)或my_object.__class__检查对象的类型。
现在您知道了实例对象是如何创建的,但是真正的创建类型/类对象(允许创建实例对象)的是什么?
实际上,这些对象也是通过实例化创建的,尽管它是
与前面提到的稍有不同的实例化类型。
除了class语句之外,还可以使用
type(cls_name, parent_class_tuple, attr_dict)创建一个新类。
例如:type('Hello', (object,), {})
将创建与前面所示相同的Hello类。
什么是type?输入元类。
type是一个元类,它是类的类,即
元类的实例。type的__class__仍然是type。
这是一个图表,显示了元类和类之间的关系,
实例:instantiate instantiate
metaclass --------------> class ----------------> instance
type.__new__() object.__new__()
当调用元类type来创建一个新类时,类似的流程如下:type.__call__()被执行
type.__new__()分配内存,然后返回新的一个类(一个元类instace),然后调用type.__init__()。
type.__init__()初始化从步骤2传递的新创建类。
您甚至可以通过子类化type来创建新的元类:class MyMeta(type):
def __new__(meta, name, bases, dct):
# do something
return super(MyMeta, meta).__new__(meta, name, bases, dct)
def __init__(cls, name, bases, dct):
# do something
super(MyMeta, cls).__init__(name, bases, dct)
然后您可以从这个MyMeta元类创建一个新类,就像您所做的那样
使用type:MyClass = MyMeta('MyClass', (object, ), {'x': 1})
或者,在定义类时使用__metaclass__,它正好具有
与上面所示的效果相同:
^{p页r 10}$