Python 3.9 MetaClass 属性与 Classmethod 属性

Posted

技术标签:

【中文标题】Python 3.9 MetaClass 属性与 Classmethod 属性【英文标题】:Python 3.9 MetaClass Property vs Classmethod Property 【发布时间】:2021-09-20 23:25:49 【问题描述】:

考虑下面的代码

from abc import ABC, ABCMeta


class MyMetaClass(ABCMeta):
    @property
    def metaclass_property(cls):
        return "result"

    # def __dir__(cls):
    #     return list(super().__dir__()) + ['metaclass_property']


class MyBaseClass(ABC, metaclass=MyMetaClass):
    @classmethod
    @property
    def baseclass_property(cls):
        return "result"


class MyClass(MyBaseClass, metaclass=MyMetaClass):
    pass


assert MyClass.baseclass_property == "result"
assert hasattr(MyClass, 'baseclass_property')
assert 'baseclass_property' in dir(MyClass)

assert MyClass.metaclass_property == "result"
assert hasattr(MyClass, 'metaclass_property')
assert 'metaclass_property' in dir(MyClass)

我注意到这会在最后一行引发断言错误。 (蟒蛇v3.9.6)。这是为什么?它是一个错误吗?可以通过手动将其添加到__dir__ 来修复它,根据两个未注释的行。

我的问题是,解决此问题的最佳方法是什么?类方法属性或元类属性之间有什么根本区别吗? (即,有什么我可以或不能做的事情,但不是另一个?)如果没有,我应该使用哪一个?

【问题讨论】:

【参考方案1】:

我认为这与属性、元类或abc 无关。

一个简单的例子:

>>> int.__mro__
(<class 'int'>, <class 'object'>)
>>> isinstance(int, type)
True
>>> '__mro__' in dir(int)
False
>>> '__mro__' in dir(type)
True

在本例中,objectint 的基类,而typeint 的元类。

dir 函数的 official documentation 明确表示它

试图产生最相关的,而不是完整的信息

如果对象是类型或类对象,则列表包含其属性的名称,并递归地包含其基类的属性。

当参数是类时,元类属性不在结果列表中

【讨论】:

以上是关于Python 3.9 MetaClass 属性与 Classmethod 属性的主要内容,如果未能解决你的问题,请参考以下文章

35.Python面向对象元类:type()__metaclass__属性实现简易ORM框架

35.Python面向对象元类:type()__metaclass__属性实现简易ORM框架

python ≥3.9 中的只读类属性,支持 `help()`

Python type class metaclass

如果 __metaclass__ 是类属性,它如何控制类的生成?

Python中的元类 -- metaclass