当您仔细观察这些方法的执行顺序时,细微的差异会变得更加明显。
class Meta_1(type):
def __call__(cls, *a, **kw):
print "entering Meta_1.__call__()"
rv = super(Meta_1, cls).__call__(*a, **kw)
print "exiting Meta_1.__call__()"
return rv
class Class_1(object):
__metaclass__ = Meta_1
def __new__(cls, *a, **kw):
print "entering Class_1.__new__()"
rv = super(Class_1, cls).__new__(cls, *a, **kw)
print "exiting Class_1.__new__()"
return rv
def __init__(self, *a, **kw):
print "executing Class_1.__init__()"
super(Class_1,self).__init__(*a, **kw)
请注意,上面的代码实际上做除了记录我们正在做的事情之外的任何事情。每个方法都遵循其父实现,即其默认值。因此,除了记录之外,它实际上就像您只是简单地声明了如下内容:
class Meta_1(type): pass
class Class_1(object):
__metaclass__ = Meta_1
现在让我们创建一个Class_1的实例
c = Class_1()
# entering Meta_1.__call__()
# entering Class_1.__new__()
# exiting Class_1.__new__()
# executing Class_1.__init__()
# exiting Meta_1.__call__()
因此,如果type 是Meta_1 的父级,我们可以想象type.__call__() 的伪实现如下:
class type:
def __call__(cls, *args, **kwarg):
# ... a few things could possibly be done to cls here... maybe... or maybe not...
# then we call cls.__new__() to get a new object
obj = cls.__new__(cls, *args, **kwargs)
# ... a few things done to obj here... maybe... or not...
# then we call obj.__init__()
obj.__init__(*args, **kwargs)
# ... maybe a few more things done to obj here
# then we return obj
return obj
从上面的调用顺序中注意到,Meta_1.__call__()(或在本例中为type.__call__())有机会影响是否最终调用Class_1.__new__() 和Class_1.__init__()。在其执行过程中,Meta_1.__call__() 可能会返回一个甚至都没有接触过的对象。以单例模式的这种方法为例:
class Meta_2(type):
__Class_2_singleton__ = None
def __call__(cls, *a, **kw):
# if the singleton isn't present, create and register it
if not Meta_2.__Class_2_singleton__:
print "entering Meta_2.__call__()"
Meta_2.__Class_2_singleton__ = super(Meta_2, cls).__call__(*a, **kw)
print "exiting Meta_2.__call__()"
else:
print ("Class_2 singleton returning from Meta_2.__call__(), "
"super(Meta_2, cls).__call__() skipped")
# return singleton instance
return Meta_2.__Class_2_singleton__
class Class_2(object):
__metaclass__ = Meta_2
def __new__(cls, *a, **kw):
print "entering Class_2.__new__()"
rv = super(Class_2, cls).__new__(cls, *a, **kw)
print "exiting Class_2.__new__()"
return rv
def __init__(self, *a, **kw):
print "executing Class_2.__init__()"
super(Class_2, self).__init__(*a, **kw)
让我们观察在反复尝试创建Class_2 类型的对象时会发生什么
a = Class_2()
# entering Meta_2.__call__()
# entering Class_2.__new__()
# exiting Class_2.__new__()
# executing Class_2.__init__()
# exiting Meta_2.__call__()
b = Class_2()
# Class_2 singleton returning from Meta_2.__call__(), super(Meta_2, cls).__call__() skipped
c = Class_2()
# Class_2 singleton returning from Meta_2.__call__(), super(Meta_2, cls).__call__() skipped
print a is b is c
True
现在观察这个实现,使用一个类的__new__() 方法来尝试完成同样的事情。
import random
class Class_3(object):
__Class_3_singleton__ = None
def __new__(cls, *a, **kw):
# if singleton not present create and save it
if not Class_3.__Class_3_singleton__:
print "entering Class_3.__new__()"
Class_3.__Class_3_singleton__ = rv = super(Class_3, cls).__new__(cls, *a, **kw)
rv.random1 = random.random()
rv.random2 = random.random()
print "exiting Class_3.__new__()"
else:
print ("Class_3 singleton returning from Class_3.__new__(), "
"super(Class_3, cls).__new__() skipped")
return Class_3.__Class_3_singleton__
def __init__(self, *a, **kw):
print "executing Class_3.__init__()"
print "random1 is still {random1}".format(random1=self.random1)
# unfortunately if self.__init__() has some property altering actions
# they will affect our singleton each time we try to create an instance
self.random2 = random.random()
print "random2 is now {random2}".format(random2=self.random2)
super(Class_3, self).__init__(*a, **kw)
请注意,即使在类上成功注册了单例,上述实现也不会阻止调用 __init__(),这在 type.__call__() 中隐式发生(type 是默认元类,如果未指定)。这可能会导致一些不良影响:
a = Class_3()
# entering Class_3.__new__()
# exiting Class_3.__new__()
# executing Class_3.__init__()
# random1 is still 0.282724600824
# random2 is now 0.739298365475
b = Class_3()
# Class_3 singleton returning from Class_3.__new__(), super(Class_3, cls).__new__() skipped
# executing Class_3.__init__()
# random1 is still 0.282724600824
# random2 is now 0.247361634396
c = Class_3()
# Class_3 singleton returning from Class_3.__new__(), super(Class_3, cls).__new__() skipped
# executing Class_3.__init__()
# random1 is still 0.282724600824
# random2 is now 0.436144427555
d = Class_3()
# Class_3 singleton returning from Class_3.__new__(), super(Class_3, cls).__new__() skipped
# executing Class_3.__init__()
# random1 is still 0.282724600824
# random2 is now 0.167298405242
print a is b is c is d
# True