【问题标题】:Order of __init_subclass__ and descriptor __set_name____init_subclass__ 和描述符 __set_name__ 的顺序
【发布时间】:2021-05-17 12:53:57
【问题描述】:

我有许多数据类,都继承自一个基类。 mapping 应该被动态添加到每个子类中,然后由描述符的__set_name__ 用于在其中设置一个键。

这是这个结构的样子:

class Model:
    def __init_subclass__(cls, *args, **kwargs):
        cls.mapping = {}

@dataclass
class ModelA(Model):
    property: str = Descriptor()

class Descriptor:
    def __set_name__(self, owner, name):
        owner.mapping[name] = 'foobar'

当描述符的__set_name__ 被调用时,mapping 似乎不存在。我尝试为ModelA 使用元类:

class Meta(type):
    def __new__(cls, name, bases, dict):
        dict['mapping'] = {}
        return super().__new__(cls, name, bases, dict)

但是还是不行。

关于我的层次结构是如何构建的,我在这里缺少什么?我怎样才能实现我所追求的加载顺序?

注意我正在使用 Python 3.8.5

【问题讨论】:

    标签: python subclass python-descriptors


    【解决方案1】:

    __set_name__ 发生在 __init_subclass__ 之前。 Here's 记录在哪里:

    当使用默认元类 type 或任何最终调用 type.__new__ 的元类时,在创建类对象后会调用以下附加自定义步骤:

    • 首先,type.__new__ 收集类命名空间中定义__set_name__() 方法的所有描述符;

    • 其次,所有这些__set_name__ 方法都使用正在定义的类和该特定描述符的分配名称来调用;

    • 最后,__init_subclass__() 钩子在新类的直接父类上按照其方法解析顺序被调用。

    【讨论】:

    • 有道理,谢谢指出!不过,我将如何以最优雅的方式解决问题?
    猜你喜欢
    • 2016-06-07
    • 2020-06-02
    • 2019-06-21
    • 1970-01-01
    • 2014-02-12
    • 2019-05-25
    • 2016-10-19
    • 1970-01-01
    相关资源
    最近更新 更多