【问题标题】:should I be afraid of the way __init_subclass__ kicks off?我应该害怕 __init_subclass__ 的启动方式吗?
【发布时间】:2019-01-10 15:23:09
【问题描述】:

我在一个项目中使用 init_subclass,当我在代码第一次在解释器中运行时遇到内置方法时,我有点犹豫——没有通过实例化直接引用包含类或其枚举的子类。

谁能告诉我发生了什么,并指出任何安全使用的例子?

class Timer():

    def __init__(self):
        pass

    def __init_subclass__(cls):
        print('Runner.', cls)
        print('Timer Dictionary :', Timer.__dict__.keys())
        # print(Timer.__init_subclass__()) # Forbidden fruit...
        pass

class Event(Timer):
    print("I'll take my own bathroom selfies...thanks anyway.")

    def __init__(self):
        print('This is nice, meeting on a real date.')

if __name__ == '__main__': # a good place for a breakpoint
        date = Event()
        date

编辑 ---------------------------------- ----

根据收到的解释,将原始代码改造成有用的东西。

class Timer():

    subclasses = {}

    def __init__(self):
        pass

    def __init_subclass__(cls, **kwargs):
        print('Runner.', cls)
        print('Timer Dictionary :', Timer.__dict__.keys())
        # print(Timer.__init_subclass__()) # Forbidden fruit...
        super().__init_subclass__(**kwargs)
        cls.subclasses[cls] = []


class Event(Timer):
    print("I'll take my own bathroom selfies...thanks anyway.")

    def __init__(self):
        print('This is nice, meeting on a real date.')
        if self.__class__ in super().subclasses:
            # get the index and link the two
            super().subclasses[self.__class__].append(self)

if __name__ == '__main__': # a good place for a breakpoint
    date = Event()
    date
    duty = Event()
    duty
    print(Timer.subclasses)

【问题讨论】:

  • 首先,为什么你Timer.__init_subclass__()无限递归? (它永远自称。)
  • 是的,已修复。谢谢。
  • __init_subclass__ 的目的是在定义子类时运行。它旨在替换元类的某些用途,因此它与类本身的创建相关,而不是父类或子类的实例化。
  • 以何种方式不安全?你担心发生什么?
  • 顺便说一句,签名应该是__init_subclass__(cls, **kwargs),你应该在方法结束时调用super().__init_subclass__(**kwargs)。这使您可以从多个父级继承他们的__init_subclass__ 方法。

标签: python class initialization subclass enumerable


【解决方案1】:

这是一个最小的例子:

class Super():
    def __init_subclass__(cls):
        print(cls)

class Sub(Super):
    pass

运行这个:

$ python test.py
<class '__main__.Sub'>

这是为什么呢?根据Python's data model docs

每当一个类从另一个类继承时,就会在该类上调用 init_subclass

Sub 继承自 Super,因此会调用 Super.__init_subclass__()

具体来说,type_new() invokes init_subclasscpython 实现中。

原因在PEP 487中有详细说明。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 2012-08-25
相关资源
最近更新 更多