使用__new__覆盖子类中的__init__

uay*_*ver 8 python methods object instance object-initializers

我有兴趣使用该__new__功能将代码注入__init__子类的功能.我从文档中了解到python将调用__init__返回的实例__new__.但是,我__init__在返回它之前更改实例值的努力__new__似乎不起作用.

class Parent(object):

    def __new__(cls, *args, **kwargs):
        new_object = super(Parent, cls).__new__(cls)
        user_init = new_object.__init__
        def __init__(self, *args, **kwargs):
            print("New __init__ called")
            user_init(self, *args, **kwargs)
            self.extra()
        print("Replacing __init__")
        setattr(new_object, '__init__', __init__)
        return new_object

    def extra(self):
        print("Extra called")

class Child(Parent):

    def __init__(self):
        print("Original __init__ called")
        super(Child, self).__init__()

c = Child()
Run Code Online (Sandbox Code Playgroud)

上面的代码打印:

Replacing __init__
Original __init__ called
Run Code Online (Sandbox Code Playgroud)

但我希望它能打印出来

Replacing __init__
New __init__ called
Original __init__ called
Extra called
Run Code Online (Sandbox Code Playgroud)

为什么不?

我觉得Python正在调用原始值__init__,无论我将其设置为什么__new__.运行内省c.__init__显示新版本已就绪,但尚未作为对象创建的一部分进行调用.

Pen*_*ian 0

我怀疑答案是这__init__是一个特殊的函数,在内部它被定义为类方法,因此不能通过在对象的实例中重新分配它来替换它。

在 Python 中,所有对象都由 C 中的 来表示PyObject,它有一个指向 a 的指针PyTypeObject。这包含一个名为的成员tp_init,我相信它包含一个指向__init__

另一种解决方案有效,因为我们修改的是类,而不是对象的实例。