在大多数著名的 OO 语言中,表达式 likeSomeClass(arg1, arg2)
将分配一个新实例,初始化该实例的属性,然后返回它。
在大多数著名的 OO 语言中,可以通过定义构造函数为每个类自定义“初始化实例的属性”部分,该构造函数基本上只是对新实例进行操作的代码块(使用提供给构造函数表达式的参数) 来设置所需的任何初始条件。在 Python 中,这对应于类的__init__
方法。
Python__new__
无非就是“分配一个新实例”部分的类似的每类定制。这当然允许您执行不寻常的事情,例如返回现有实例而不是分配新实例。所以在 Python 中,我们不应该真的认为这部分必然涉及分配;我们所需要的只是__new__
从某个地方提出一个合适的实例。
但这仍然只是工作的一半,Python 系统无法知道有时你想在__init__
之后运行另一半工作( ),而有时你不想。如果你想要这种行为,你必须明确地说出来。
通常,您可以重构以便只需要__new__
,或者不需要__new__
,或者__init__
在已经初始化的对象上表现不同。但如果你真的想这样做,Python 实际上确实允许你重新定义“工作”,所以SomeClass(arg1, arg2)
不一定 call__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
然而,这可能是比这种情况真正需要的更深层次的魔法!