有没有办法在 Python 中调用子类定义的方法?

Posted

技术标签:

【中文标题】有没有办法在 Python 中调用子类定义的方法?【英文标题】:Is there a way to call a method on definition of a subclass in Python? 【发布时间】:2019-11-30 17:41:36 【问题描述】:

__init__ 方法定义了在创建类实例时所做的工作。创建子类时我可以做一些等效的事情吗?

假设我有抽象类Entity

class Entity:
    def __onsubclasscreation__(cls):
        for var in cls.__annotations__:
            cls.__dict__[var] = property(lambda self:self.vars[var])

这意味着每当我定义一个继承自 Entity 的新类时,该类的所有带注释的变量都会收到一个 getter:

class Train(Entity):
    wagons: int
    color: str

>>> t = Train()
>>> t.vars["wagons"] = 5
>>> t.wagons
5

我不能在实例化时这样做,因为需要在类中定义属性,而我不能在超类中这样做,因为我不知道需要哪些属性。有没有办法在子类创建时动态地做一些事情?

【问题讨论】:

为什么需要一个只返回一个值的getter? 这只是一个例子,getter当然会做其他事情。 更多信息__init_subclass__: ***.com/questions/45400284/… 每个属性本质上是相同的getter,还是for循环也只是一个例子? 我问是因为自定义的类似属性的描述符可能更合适。例如,class Train: wagons = mycustomproperty(int) color = mycustomproperty(str) 【参考方案1】:

您正在描述__init_subclass__钩子(docs)的基本用法:

每当一个类从另一个类继承时,就会在该类上调用__init_subclass__。这样,就可以编写改变子类行为的类。

>>> class A: 
...     def __init_subclass__(cls): 
...         print(f"init cls") 
...
>>> class B(A): 
...     pass 
...
init <class '__main__.B'>

更多信息请参见PEP 487 -- Simpler customisation of class creation。

注意: 这是 3.6+ 的功能。在较旧的 Python 版本中,使用元类 __new__ 来实现相同的目的:

>>> class MyMeta(type):
...     def __new__(meta, name, bases, class_dict):
...         print("MyMeta.__new__", meta, name, bases, class_dict)
...         return type.__new__(meta, name, bases, class_dict)
...
>>> class A(metaclass=MyMeta):
...     pass
...
MyMeta.__new__ <class '__main__.MyMeta'> A () '__module__': '__main__', '__qualname__': 'A'
>>> class B(A):
...     pass
...
MyMeta.__new__ <class '__main__.MyMeta'> B (<class '__main__.A'>,) '__module__': '__main__', '__qualname__': 'B'

【讨论】:

【参考方案2】:

您也许可以将此功能抽象到另一个方法中,然后从超类的构造函数中调用该方法。如果子类调用超类的构造函数(它们应该这样做),那么该方法将在子类被实例化时被执行。

class Entity:
    @classmethod
    def _onsubclasscreation(cls):
        for var in cls.__annotations__:
            cls.__dict__[var] = property(lambda self:self.vars[var])

    def __init__(self):
        ...
        self.__class__._onsubclasscreation()

然后,只要子类不覆盖_onsubclasscreation() 的功能,行为就应该符合预期。

【讨论】:

以上是关于有没有办法在 Python 中调用子类定义的方法?的主要内容,如果未能解决你的问题,请参考以下文章

Python-类继承

python - 构造函数

Python中子类怎样调用父类方法

Python基础-接口与归一化设计抽象类继承顺序子类调用父类,多态与多态性

在JAVA中,子类继承父类,父类可以调用子类继承父类的方法,父类为啥不能调用子类自己定义的方法呢

在 Raku 中测试私有方法