如何让子类自动调用父类__init__?

时间:2013-09-26 13:26:14

标签: python python-3.x

我有一个名为CacheObject的类,许多类都从它扩展。

现在我需要在这个类的所有类中添加一些常见内容,所以我写这个

class CacheObject(object):

    def __init__(self):
        self.updatedict = dict() 

但是子类没有获得updatedict属性。我知道调用super init函数在python中是可选的,但是有一种简单的方法可以强制所有这些函数添加init而不是遍历所有类并修改它们一个接一个?

5 个答案:

答案 0 :(得分:3)

我建议使用非代码修复:

您的子类在使用其中定义的任何其他方法之前应该调用super().__init__()的文档。

这不是一个罕见的限制。例如,请参阅标准库中threading.Thread的文档,其中包含:

  

如果子类重写构造函数,它必须确保在对线程执行任何其他操作之前调用基类构造函数(Thread.__init__())。

可能还有很多其他的例子,我碰巧打开了这个doc页面。

答案 1 :(得分:2)

这不是您要求的,而是如何将updatedict设为属性,以便不需要在__init__中设置:

class CacheObject(object):
    @property
    def updatedict(self):
        try:
            return self._updatedict
        except AttributeError:
            self._updatedict = dict()
            return self._updatedict

希望这可以达到真正的目标,你不需要触及每个子类(当然,除了确保没有使用名为updatedict的属性之外)。

但是,有一些奇怪的问题,因为它与您在updatedict中设置__init__不同。例如,CacheObject().__dict__的内容不同。它没有键updatedict,因为我把这个键放在了类中,而不是放在每个实例中。

答案 2 :(得分:1)

您可以覆盖__new__。只要你的基类在没有调用__new__的情况下没有覆盖super().__new__,那么你就可以了。

class CacheObject(object):
    def __new__(cls, *args, **kwargs):
        instance = super().__new__(cls, *args, **kwargs)
        instance.updatedict = {}
        return instance

class Foo(CacheObject):
    def __init__(self):
        pass

然而,正如一些评论者所说,这种动机似乎有点阴暗。您应该只是添加超级调用。

答案 3 :(得分:1)

我遇到的情况是,我希望类在调用自己的类之前始终按顺序调用它们的基类的构造函数。以下是应该做你想做的Python3代码:

  class meta(type):
    def __init__(cls,name,bases,dct):
      def auto__call__init__(self, *a, **kw):
        for base in cls.__bases__:
          base.__init__(self, *a, **kw)
        cls.__init__child_(self, *a, **kw)
      cls.__init__child_ = cls.__init__
      cls.__init__ = auto__call__init__

  class A(metaclass=meta):
    def __init__(self):
      print("Parent")

  class B(A):
    def __init__(self):
      print("Child")

为了说明,它的行为如下:

>>> B()
Parent
Child
<__main__.B object at 0x000001F8EF251F28>
>>> A()
Parent
<__main__.A object at 0x000001F8EF2BB2B0>

答案 4 :(得分:-1)

您可以在类中添加装饰器:

def my_decorator(cls):
    old_init = cls.__init__
    def new_init(self):
        self.updatedict = dict()
        old_init(self)
    cls.__init__ = new_init
    return cls

@my_decorator
class SubClass(CacheObject):
    pass

如果要自动将装饰器添加到所有子类,请使用元类:

class myMeta(type):
    def __new__(cls, name, parents, dct):
        return my_decorator(super().__new__(cls, name, parents, dct))

class CacheObject(object, metaclass=myMeta):
    pass