gpt4 book ai didi

python - 类方法上的装饰器

转载 作者:行者123 更新时间:2023-12-01 00:29:39 25 4
gpt4 key购买 nike

我有一些子类,它们从父类继承了一些基本功能。子类应该有一个通用构造函数 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有关,但我无法弄清楚。

这个调用有什么问题吗?

更新:一般来说,错误是 __init__ 不返回对象。

由于答案中的提示和想法,我修改了代码以实现我的需要:

class Parent:

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

@staticmethod
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

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


class ChildWithOneName(Parent):

@classmethod
@Parent.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, b)
print("Does the same as in it's __init__ method")
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}"


class GodChild(Parent):

@classmethod
@Parent.decorate_with_some_magic
def prepare_and_connect_constructor(cls, a, names):
""" use the generic connection decorator right on object creation """
obj = super().__new__(cls)
obj.__init__(a, names)
# perform some more specific operations
obj.register_all_names(names)
print("And does some more stuff than in it's __init__ method")
return obj

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

def register_all_names(self, names=[]):
self.verified_names = []

def verify(text):
return True

for name in names:
if verify(name):
self.verified_names.append(name)


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


if __name__ == '__main__':
print(ChildWithOneName.prepare_and_connect_constructor("special child", "needs some help"), end='\n\n')
print(GodChild.prepare_and_connect_constructor("unknown child", "needs some verification"), end='\n\n')
print(ChildWithOneName("my child", "is clean and doesn't need extra magic"))
  • decorate_with_some_magic 现在是 Parent 类的一部分(使用静态方法),因为它是相关的通用功能
  • 每个子类(为了便于说明而添加了一个)都有自己的 prepare_and_connect_constructor classmethod,它调用自己的构造函数,并可选择执行一些额外的工作

最佳答案

您对魔术方法 __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__

关于python - 类方法上的装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58275513/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com