2013-09-26 21 views
2

我有一个名为CacheObject的类,并且有很多类从它延伸。如何使子类自动调用父类__init__?

现在我需要从这个类中添加的所有类的共同的东西,所以我写这篇

class CacheObject(object): 

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

但子类没有获得updatedict attribute.i知道调用超级初始化函数是蟒蛇可选,但是有没有一种简单的方法可以强制所有人添加init,而不是遍历所有类并逐个修改它们?如果您想将装饰自动添加到所有子类,使用元类

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 
+0

您是否正在寻找一种解决方案,该解决方案应该能够与多重继承协同工作?如果是这样,无论如何你必须调用'super'。如果子类没有定义自己的'__init__',则会自动调用基类的'__init__'。否则,它们必须包含对“super().__ init__”的调用。 – shx2

+3

“我知道在python中调用超级初始化函数是可选的” - 如果您希望基类可以自由运行初始化代码,则不是。 –

+0

如果我反向控制该子类仍然需要修改。所有子类__init__必须重命名。 – user2003548

回答

3

我建议非代码修复:

文件是super().__init__()应该由你的子类,他们使用它定义的任何其他方法之前被调用。

这不是一个不常见的限制。见,例如,标准库为threading.Thread的文档,它说:

如果子类覆盖的构造,它必须确保做其他事情的线程之前调用基类构造函数(Thread.__init__()) 。

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

-1

您可以在装饰添加到您的类。只要你的基类不会调用super().__new__覆盖__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 

但是,正如一些评论者所说,这样做的动机似乎有点阴暗。您应该也许应该添加超级通话。

+0

'CacheObject'的所有实例都会共享_same_字典 - 这绝对不是OP想要的。他希望每个实例都有一个实例属性。另外,python3不再使用'__metaclass__',它现在是'类CacheObject(object,metaclass = myMeta)'。 – mata

1

您可以覆盖__new__

2

这不是你问什么,而是怎么样让updatedict的属性,所以它并不需要在__init__进行设置:

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

希望这实现了真正的目标,你不希望触及每个子类(当然,除了确保没有使用称为updatedict的属性)。

有一些奇怪的陷阱,不过,因为它是从设置在__init__updatedict在你的问题不同。例如,CacheObject().__dict__的内容是不同的。它没有密钥updatedict,因为我已将该密钥放入课程中,而不是在每个实例中。