我有子类,它们从父类继承了一些基本功能。子类应具有通用的构造函数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__
和__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__
装饰器处理可调用对象。由于调用函数和启动类之间没有区别,因此可以直接在类上使用装饰器:
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