类方法的装饰器

问题描述 投票:0回答:2

我有子类,它们从父类继承了一些基本功能。子类应具有通用的构造函数prepare_and_connect_constructor(),该构造函数对父类的对象创建具有不可思议的作用。为简单起见,魔术是通过一个基于函数的简单装饰器完成的(最终,它应该是父类的一部分)。

def decorate_with_some_magic(func):
    def prepare_and_connect(*args, **kwargs):
        print("prepare something")
        print("create an object")
        obj = func(*args, **kwargs)
        print("connect obj to something")
        return obj

    return prepare_and_connect


class Parent:

    def __init__(self, a):
        self.a = a

    def __repr__(self):
        return f"{self.a}"


class Child(Parent):

    @classmethod
    @decorate_with_some_magic
    def prepare_and_connect_constructor(cls, a, b):
        """ use the generic connection decorator right on object creation """
        obj = super().__init__(a)
        # put some more specific attributes (over the parents class)
        obj.b = b
        return obj

    def __init__(self, a, b):
        """ init without connecting """
        super().__init__(a)
        self.b = b

    def __repr__(self):
        return f"{self.a}, {self.b}"


if __name__ == '__main__':
    print(Child.prepare_and_connect_constructor("special child", "needs some help"))

使用此代码我终于得到了

obj = super().__init__(a)
  TypeError: __init__() missing 1 required positional argument: 'a'

运行prepare_and_connect_constructor()时。

实际上,我希望super.__init__(a)调用应与Child.__init__中的调用相同。我想原因与classmethod有关,但我想不出来。

这个电话怎么了?

python decorator class-method
2个回答
0
投票

您对魔术方法__init____new__略有误解。 __new__创建一个新对象,例如返回该类的实例。 __init__只是修改对象。因此,可以轻松解决您的问题:

@classmethod
@decorate_with_some_magic
def prepare_and_connect_constructor(cls, a, b):
    """ use the generic connection decorator right on object creation """
    obj = super().__new__(cls)
    obj.__init__(a)
    # put some more specific attributes (over the parents class)
    obj.b = b
    return obj

但是我不认为您应该这样使用它。相反,您可能应该覆盖__new__


0
投票

装饰器处理可调用对象。由于调用函数和启动类之间没有区别,因此可以直接在类上使用装饰器:

def decorate_with_some_magic(func):
    def prepare_and_connect(*args, **kwargs):
        print("prepare something")
        print("create an object")
        obj = func(*args, **kwargs)
        print("connect obj to something")
        return obj

    return prepare_and_connect


class Parent:

    def __init__(self, a):
        self.a = a

    def __repr__(self):
        return f"{self.a}"

@decorate_with_some_magic
class Child(Parent):

    def __init__(self, a, b):
        """ init without connecting """
        super().__init__(a)
        self.b = b

child = Child(10, 20)

输出:

prepare something
create an object
connect obj to something
© www.soinside.com 2019 - 2024. All rights reserved.