在大多数众所周知的OO语言中,类似的表达式SomeClass(arg1, arg2)
将分配一个新实例,初始化该实例的属性,然后返回它。
在大多数著名的OO语言中,可以通过定义构造函数为每个类自定义“初始化实例的属性”部分,该构造函数基本上只是在新实例上运行的代码块(使用提供给构造函数表达式的参数) )来设置所需的任何初始条件。在Python中,这对应于class的__init__
方法。
Python的__new__
功能无非就是“分配新实例”部分的类似的按类自定义。当然,这允许您执行不同寻常的操作,例如返回现有实例而不是分配新实例。因此,在Python中,我们不应该真的认为这部分必然涉及分配。我们所需要的只是__new__
从某个地方提出一个合适的实例。
但这仍然只是工作的一半,Python系统无法知道有时您希望__init__
稍后再执行另一部分工作(),而有时又不想。如果您想要这种行为,则必须明确地说出。
通常,您可以重构,因此只需要__new__
,或者不需要__new__
,或者这样__init__
就可以在已初始化的对象上表现不同。但是,如果你真的想,Python不竟让你重新定义“工作”,所以SomeClass(arg1, arg2)
不一定需要__new__
后面__init__
。为此,您需要创建一个元类,并定义其__call__
方法。
元类只是类的类。而类的__call__
方法控制了当您调用类的实例时会发生什么。因此,metaclass的__call__
方法控制了您调用类时发生的事情。即,它允许您从头到尾重新定义实例创建机制。在此级别上,您可以最优雅地实现完全非标准的实例创建过程,例如单例模式。事实上,用了不到10行代码就可以实现一个Singleton
元类是那么甚至不要求你与futz __new__
可言,并且可以将任何通过简单地增加,否则正常的,定义为单__metaclass__ = Singleton
!
class Singleton(type):
def __init__(self, *args, **kwargs):
super(Singleton, self).__init__(*args, **kwargs)
self.__instance = None
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super(Singleton, self).__call__(*args, **kwargs)
return self.__instance
但是,这可能比这种情况下真正应具有的魔力还要深!