【问题标题】:How does the python determine the appropriate metaclass?python如何确定合适的元类?
【发布时间】:2020-04-04 15:54:29
【问题描述】:

我可能在official doc 中找到答案,但我仍然无法得到它。您能否在第二种和第三种情况下给我更详细或更直接的解释?如果你能给我一些例子,我将不胜感激!

类定义的适当元类确定如下:

  • 如果没有给出基类和显式元类,则使用type()
  • 如果给出了一个明确的元类,并且它不是 type() 的实例,那么它直接用作元类;
  • 如果type() 的实例作为显式元类给出,或者定义了基类,则使用派生度最高的元类。

【问题讨论】:

    标签: python grammar cpython


    【解决方案1】:

    假设您试图通过一个元类(在本例中是两个元类)来实现单例模式。

    class Singleton(type):
        _inst = {}
    
        def __call__(cls, *args, **kwargs):
            return cls._inst.setdefault(cls, super().__call__(*args, **kwargs))
    
    class Singleton2(Singleton):
        def __call__(cls, *args, **kwargs):
            return super().__call__(*args, **kwargs)
    
    
    
    class SingletonClass1(metaclass=Singleton):
        pass
    
    
    class SingletonClass2(SingletonClass1, metaclass=Singleton2):
        pass
    
    
    class SingletonClass3():
        pass
    
    
    class SingletonClass4(SingletonClass2, metaclass=Singleton):
        pass
    

    type(class_obj)函数返回class_obj的元类。

    这是你的案例:

    1. 如果没有给出基类和显式元类,则使用 type();

      type(SingletonClass3) --> <class 'type'>

    2.如果给出了一个显式的元类,并且它不是type()的实例,那么直接作为元类使用;

    `type(SingletonClass2) --> <class '__main__.Singleton2'>`
    

    3. 如果将 type() 的实例作为显式元类给出,或者定义了基类,则使用最派生的元类;

    `type(SingletonClass4) --> <class '__main__.Singleton2'>`
    

    如果你从SingletonClass1继承SingletonClass2却忘记从Singleton继承Singleton2,会导致TypeError。

    派生度最高的元类是所有这些元类的子类型 候选元类。如果没有一个候选元类满足 标准,那么类定义将因 TypeError 而失败。

    更新: 元类可以是函数,不是type 的实例,所以第二种情况(如果给出了明确的元类并且它不是类型的实例)可以与此相关。这是一个元类函数的单例实现。

    def singleton_func(class_name, bases, attrs):
        _inst = {}
    
        def custom_new(cls):
            return _inst.setdefault(cls, object.__new__(cls))
    
        attrs['__new__'] = custom_new
        return type(class_name, bases, attrs)
    
    
    class SingletonClass5(metaclass=singleton_func):
        pass
    

    【讨论】:

    • 为什么文档说“type() 的实例作为显式元类给出”而不是“type() 的子类......”。我的意思是大多数用户定义的类都是“类型()的实例”,不继承自type 的类可以是元类吗?
    • 根据此评论更新了答案,是否涵盖了您的问题?
    • 还有一件事...如果我有一个定义为class Singleton3(type, metaclass=Singleton) 的元类。是第二种情况吗?
    • 我认为是第三个,因为 type() 的实例是作为显式元类给出的。
    猜你喜欢
    • 1970-01-01
    • 2012-08-11
    • 2017-10-06
    • 1970-01-01
    • 2019-03-18
    • 2018-12-26
    • 2020-10-23
    • 1970-01-01
    • 2019-05-27
    相关资源
    最近更新 更多