这可能是一个重复的问题,但是我没有找到适合我的情况的解决方案
我有以下两个类
类账户
class Account():
def __init__(self, acnt_type, id, name):
self.account_type = acnt_type
self.id = id
self.name = name
def create_account(self) -> dict:
account_details ={}
account_details['acnt_type']= self.account_type
account_details['id']= self.id
account_details['name']=self.name
return account_details
@property
def acount_type(self):
return self.account_type
@acount_type.setter
def account_type(self, new_acount_value):
self.account_type = new_acount_value
类客户
class Customer(Account):
def __init__(self,acount_type, id, name):
super().__init__(acount_type, id, name)
@Account.account_type.getter
def acount_type(self):
return super(Customer, Customer).account_type.__get__(self)
@Account.account_type.setter
def account_type(self, new_acount_value):
super(Customer, Customer).account_type.__set__(self,new_acount_value)
调用类
acnt_type, id, name = ('savings', '101','Umesh')
obj = Customer(acount_type=acnt_type, id= id, name=name)
details = obj.create_account()
print(details)
obj.account_type='Fixed'
print(details)
但是低于error
RecursionError: maximum recursion depth exceeded
#预计:
Initial run
details = obj.create_account()
print(details)
{'acnt_type': 'savings', 'id': '101', 'name': 'Umesh'}
-- Updating account type
obj.account_type='Fixed'
print(details)
{'acnt_type': 'Fixed', 'id': '101', 'name': 'Umesh'}
有解决办法吗?是正确的方法,而继承属性从父类在python?
- 正确的属性名称 不要在构造函数中使用setter。创建私有字段并使用它继承不需要额外的步骤。属性被自动继承。
class Account():
def __init__(self, acnt_type, id, name):
self.__account_type = acnt_type
self.id = id
self.name = name
def create_account(self) -> dict:
account_details = {}
account_details['acnt_type'] = self.account_type
account_details['id'] = self.id
account_details['name'] = self.name
return account_details
@property
def account_type(self):
return self.__account_type
@account_type.setter
def account_type(self, new_acount_value):
self.__account_type = new_acount_value
class Customer(Account):
def __init__(self, acount_type, id, name):
super().__init__(acount_type, id, name)
acnt_type, id, name = ('savings', '101', 'Umesh')
obj = Customer(acount_type=acnt_type, id=id, name=name)
print(obj.create_account())
# {'acnt_type': 'savings', 'id': '101', 'name': 'Umesh'}
obj.account_type = 'Fixed'
print(obj.create_account())
# {'acnt_type': 'Fixed', 'id': '101', 'name': 'Umesh'}
您的问题不在于继承本身,而在于您在基类本身中使用与属性存储相同的属性名称。
当你这样做的时候:
@property
def acount_type(self):
return self.account_type
这将单独给你一个递归错误-因为self.account_type
是触发account_type
getter被调用的代码。
如果在属性内部进行属性访问时使用单个下划线("_"),就可以避免名称冲突,一切都会正常工作:
@property
def acount_type(self):
return self._account_type
(setter也是如此)。
至于继承:这个工作属性将像它在任何子类上一样工作,并且您正在重新创建属性的方式是正确的(使用@Account.account_type.getter
来修饰对基类属性的getter的重写)。然而,在你为getter做了这些之后,你不应该使用相同的策略来创建"setter",因为它将基于基类的属性创建一个新的setter,而不是基于你刚刚在子类中为其创建setter的属性。换句话说:
class Parent:
@property
def prop(self):
# base getter
...
@prop.setter(self, v):
# base setter
class Child(Parent):
@Parent.prop.getter
def prop(self):
# fine, this creates a new property, with a new getter on the child
...
parent_value = super().prop
# code transforming parent_value if needed
...
return parent_value
@Parent.prop.setter # Incorrect
def prop(self, value):
#This will duplicate the property in Parent, and create a new, child, setter. But the child getter above will be forgotten
相反,在重写子类的getter之后,简单地像这样修饰setter:
class Child(Parent):
@Parent.prop.getter
def prop(self):
# fine, this creates a new property, with a new getter on the child
...
@prop.setter
def prop(self, value):
#This will add a new setter to the property created with the new getter above
...
# transform value if needed
super(Child, Child).prop.__set__(self, value)
最后,正如您在上面的代码片段中看到的那样,使用super()
访问超类中定义的属性的方法。对于读取属性的目的,super()的无参数形式可以工作—但是为了设置或删除属性,您必须检索属性对象本身,并显式调用其__set__
或__delete__
方法:
class Child:
...
@prop.setter
def prop(self, value):
...
super(Customer, Customer).account_type.__set__(self, value)