【发布时间】:2020-02-05 02:25:24
【问题描述】:
我有从父类继承一些基本功能的子类。
子类应该有一个通用构造函数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_constructorclassmethod,它调用自己的构造函数并选择性地执行一些额外的工作
【问题讨论】:
-
__init__不返回任何内容,并且由于您从类方法调用super,super().__init__需要一个显式实例作为其第一个参数。 -
不错,没想到这个
标签: python decorator class-method