4

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

现在我需要在这个类的所有类上添加一些通用的东西所以我写了这个

class CacheObject(object):

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

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

4

5 回答 5

8

我的情况是,我希望类在调用自己的构造函数之前总是按顺序调用它们的基类的构造函数。以下是应该执行您想要的操作的 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>
于 2018-06-12T14:01:17.720 回答
5

我建议一个非代码修复:

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

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

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

可能还有很多其他的例子,我只是碰巧打开了那个文档页面。

于 2013-09-26T22:56:10.457 回答
3

这不是您要求的,但是如何创建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,因为我把钥匙放在了课堂上,而不是在每个实例中。

于 2013-09-26T22:45:05.283 回答
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

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

于 2013-09-26T14:16:25.067 回答
-2

你可以在你的类中添加一个装饰器:

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
于 2013-09-26T13:55:22.890 回答