Python 中的元类
MetaClass in Python
我正在尝试为我的 Class 创建一个 Meta-Class。
我试图在 meta-class
中打印关于我的 class 的信息
现在我已经为 class 创建了两个对象
但是创建第二个对象时没有引用我的 Meta-Class
Meta Class 每个 Class 只调用一次吗??
任何帮助将不胜感激
谢谢
class Singleton(type):
def __new__(cls,name,bases,attr):
print (f"name {name}")
print (f"bases {bases}")
print (f"attr {attr}")
print ("Space Please")
return super(Singleton,cls).__new__(cls,name,bases,attr)
class Multiply(metaclass = Singleton):
pass
objA = Multiply()
objB = Multiply()
print (objA)
print (objB)
是 - 只有在创建 class 时才调用 metaclass 的 __new__
和 __init__
方法。之后,在您的示例中,class 将绑定到 Multiply
名称。在许多方面,它就像 Python 中的任何其他对象一样。当您执行 objA = Multiply()
时,您并不是在创建 type(Multiply)
的新实例,它是元 class - 您正在创建 Multiply
本身的新实例:Multiply.__new__
和 Multiply.__init__
被调用。
现在,有这样的:Python 中的机制在创建实例时调用 __new__
和 __init__
是元 class __call__
方法。也就是说,就像当您使用 __call__
方法创建任何 class 并将其实例与调用语法 obj()
一起使用时,将调用 type(obj).__call__(obj)
,当您执行 Multiply()
所谓的(在这种情况下)是 Singleton.__call__(Multiply)
。
由于未实现,因此调用了 Singleton 的 superclass,即 type
__call__
方法 - 正是在其中调用了 Multiply.__new__
和 __init__
.
就是说,上面的代码中没有任何内容会使您的 classes 表现得像“单例”。 更重要的是您不需要元class就可以在Python中拥有一个单例。这个东西不知道是谁发明的,一直在流传。
首先,如果你真的需要一个单例,你需要做的就是写一个普通的class,没有什么特别的,创建你的单例,然后记录应该使用该实例。正如人们使用 None
一样 - 没有人会不断获得对 Nonetype
的引用并不断调用它来获得 None
引用:
class _Multiply:
...
# document that the code should use this instance:
Multiply = _Multiply()
second 或者,如果您的代码需要实例化 class 应该是将要使用的单例,您可以使用class' __new__
方法本身来控制实例化,不需要 metaclass:
class Multiply:
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
# insert any code that would go in `__init__` here:
...
...
return cls._instance
Third只是为了演示,请不要使用这个,metaclass机制有单例可以在 __call__
方法中构建:
class Singleton(type):
registry = {}
def __new__(mcls,name,bases,attr):
print(f"name {name}")
print(f"bases {bases}")
print(f"attr {attr}")
print("Class created")
print ("Space Please")
return super(Singleton,mcls).__new__(cls,name,bases,attr)
def __call__(cls, *args, **kw):
registry = type(cls).registry
if cls not in registry:
print(f"{cls.__name__} being instantiated for the first time")
registry[cls] = super().__call__(*args, **kw)
else:
print(f"Attempting to create a new instance of {cls.__name__}. Returning single instance instead")
return registry[cls]
class Multiply(metaclass = Singleton):
pass
我正在尝试为我的 Class 创建一个 Meta-Class。 我试图在 meta-class
中打印关于我的 class 的信息现在我已经为 class 创建了两个对象 但是创建第二个对象时没有引用我的 Meta-Class
Meta Class 每个 Class 只调用一次吗??
任何帮助将不胜感激
谢谢
class Singleton(type):
def __new__(cls,name,bases,attr):
print (f"name {name}")
print (f"bases {bases}")
print (f"attr {attr}")
print ("Space Please")
return super(Singleton,cls).__new__(cls,name,bases,attr)
class Multiply(metaclass = Singleton):
pass
objA = Multiply()
objB = Multiply()
print (objA)
print (objB)
是 - 只有在创建 class 时才调用 metaclass 的 __new__
和 __init__
方法。之后,在您的示例中,class 将绑定到 Multiply
名称。在许多方面,它就像 Python 中的任何其他对象一样。当您执行 objA = Multiply()
时,您并不是在创建 type(Multiply)
的新实例,它是元 class - 您正在创建 Multiply
本身的新实例:Multiply.__new__
和 Multiply.__init__
被调用。
现在,有这样的:Python 中的机制在创建实例时调用 __new__
和 __init__
是元 class __call__
方法。也就是说,就像当您使用 __call__
方法创建任何 class 并将其实例与调用语法 obj()
一起使用时,将调用 type(obj).__call__(obj)
,当您执行 Multiply()
所谓的(在这种情况下)是 Singleton.__call__(Multiply)
。
由于未实现,因此调用了 Singleton 的 superclass,即 type
__call__
方法 - 正是在其中调用了 Multiply.__new__
和 __init__
.
就是说,上面的代码中没有任何内容会使您的 classes 表现得像“单例”。 更重要的是您不需要元class就可以在Python中拥有一个单例。这个东西不知道是谁发明的,一直在流传。
首先,如果你真的需要一个单例,你需要做的就是写一个普通的class,没有什么特别的,创建你的单例,然后记录应该使用该实例。正如人们使用 None
一样 - 没有人会不断获得对 Nonetype
的引用并不断调用它来获得 None
引用:
class _Multiply:
...
# document that the code should use this instance:
Multiply = _Multiply()
second 或者,如果您的代码需要实例化 class 应该是将要使用的单例,您可以使用class' __new__
方法本身来控制实例化,不需要 metaclass:
class Multiply:
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
# insert any code that would go in `__init__` here:
...
...
return cls._instance
Third只是为了演示,请不要使用这个,metaclass机制有单例可以在 __call__
方法中构建:
class Singleton(type):
registry = {}
def __new__(mcls,name,bases,attr):
print(f"name {name}")
print(f"bases {bases}")
print(f"attr {attr}")
print("Class created")
print ("Space Please")
return super(Singleton,mcls).__new__(cls,name,bases,attr)
def __call__(cls, *args, **kw):
registry = type(cls).registry
if cls not in registry:
print(f"{cls.__name__} being instantiated for the first time")
registry[cls] = super().__call__(*args, **kw)
else:
print(f"Attempting to create a new instance of {cls.__name__}. Returning single instance instead")
return registry[cls]
class Multiply(metaclass = Singleton):
pass