首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python中的MetaClass

Python中的MetaClass
EN

Stack Overflow用户
提问于 2020-08-16 11:49:17
回答 1查看 159关注 0票数 0

我正试图为我的班级创建一个元类。我试着用元类打印有关我们班的信息。

现在我已经创建了类的两个对象,但是第二个对象是在不引用我的元类的情况下创建的。

元类每个类只被调用一次吗??

如有任何帮助,将不胜感激。

谢谢

代码语言:javascript
复制
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)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-16 13:42:34

是的-只有在创建类时才调用元类的__new____init__方法。之后,在您的示例中,类将绑定到Multiply名称。在许多方面,它只是一个对象,就像Python中的任何其他对象一样。当您执行objA = Multiply()时,您不是在创建type(Multiply)的新实例,它是元类--您正在创建Multiply本身的一个新实例:调用Multiply.__new__Multiply.__init__

下面是这样的:在创建实例时调用__new____init__的Python机制是元类__call__方法中的代码。也就是说,就像使用__call__方法创建任何类并使用调用语法obj()的实例来调用type(obj).__call__(obj)一样,当您执行Multiply()时(在本例中)是Singleton.__call__(Multiply)。由于它没有实现,因此调用了辛格尔顿的超类,即type __call__方法--在那里调用了Multiply.__new____init__

也就是说,上面的代码中没有任何东西可以使您的类表现为"singletons“。--更重要的是,--您不需要一个元类就可以在Python中拥有一个单独的实例。我不知道这东西是谁发明的,但它一直在四处流传。

First,如果您确实需要一个单例,只需编写一个普通的类,没有特殊的任何东西,创建您的单个实例,并记录应该使用的实例。就像人们使用None一样,没有人会一直获取对Nonetype的引用,并不断调用它以获得None引用:

代码语言:javascript
复制
class _Multiply:
   ...

# document that the code should use this instance:
Multiply = _Multiply()

或者,如果您的代码需要实例化应该是单个实例的类,则可以使用类的方法本身来控制实例化,而不需要元类:

代码语言:javascript
复制
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

第三代仅为演示目的,请不要使用此方法,可以在__call__方法中构建元类机制来具有单元素:

代码语言:javascript
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63436512

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档