有没有一种方法可以在Python中定义子类的方法?

时间:2019-07-22 17:45:54

标签: python inheritance methods subclass

__init__方法定义了创建类实例时要执行的操作。创建子类时,我可以做一些等效的事情吗?

假设我有抽象类Entity

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

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

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

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

我无法在实例化上执行此操作,因为属性需要在类中定义,而在超类中则不能执行,因为我不知道将需要哪些属性。有什么方法可以动态地创建子类吗?

2 个答案:

答案 0 :(得分:4)

您正在描述__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'}

答案 1 :(得分:0)

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

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()的功能,其行为就应该是预期的。