【问题标题】:Execute code when extending a class in Python在 Python 中扩展类时执行代码
【发布时间】:2014-03-12 11:07:21
【问题描述】:

当一个类被另一个类扩展时,有没有办法在 Python 中执行一些代码?更准确地说,我想自动保留所有扩展基类的类的寄存器。因此,我想写这样的东西:

class Base:

    subclasses = {}

    @classmethod
    def extending(cls, subclass):
        cls.subclasses[subclass.__name__] = subclass

class Extend1(Base):
    pass

class Extend2(Base):
    pass

在这段代码之后,我希望 Base.subclasses 包含指向两个扩展类的链接。

您能建议一种方法来完成这项工作吗?或者,也许,提供一个等效的解决方案?

【问题讨论】:

    标签: python class subclass introspection


    【解决方案1】:

    这显然是元类的应用程序。也就是说,如果你想改变 C 类的行为,那么你应该改变 C 本身的类,它是一个元类,通常是type。这是一个解决方案的存根:

    class Meta(type):
        def __new__(cls, clsname, bases, dct):
            res = type.__new__(cls, clsname, bases, dct)
            for cls in bases:
                if isinstance(cls, Meta):
                    try:
                        cls.extending(res)
                    except AttributeError:
                        pass
            return res
    

    我从type 继承来创建一个元类来拦截类的创建并将创建的类存储在基础_subclass 属性中。然后用

    class Base(object):
        __metaclass__ = Meta
    
        subclasses = {}
    
        @classmethod
        def extending(cls, subclass):
            cls.subclasses[subclass.__name__] = subclass
    
    class Extend1(Base):
        pass
    
    class Extend2(Base):
        pass
    

    然后

    >>> Base.subclasses
    {'Extend1': __main__.Extend1, 'Extend2': __main__.Extend2}
    

    非常重要的一点:元类是inherited(我认为这不是这里的正确术语)。因此Extend1Extend2 也是Meta 的实例:

    >>> type(Extend1)
    <class '__main__.Meta'>
    

    【讨论】:

      【解决方案2】:

      实际上,如果您只对子类感兴趣,python 可以自动为您提供。所有新样式类都有一个__subclasses__() 方法,该方法返回所有这些类的直接后代。

      >>> class Base(object):
      ...     pass
      ...
      >>> class Child(Base):
      ...     pass
      ...
      >>> Base.__subclasses__()
      [<class '__main__.Child'>]
      >>>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-04
        • 2022-06-10
        • 2011-05-12
        • 1970-01-01
        相关资源
        最近更新 更多