继承和dunder方法? [英] Inheritance and dunder methods?
问题描述
我目前正在学习 OOP,但遇到了 dunder 方法和继承的问题.
我有 2 个继承到子类的父类(都有自己的 init),我想要一个在所有类中初始化的数据的字符串表示形式.
这就是问题所在:
#Parent class 1:班级联系人:all_contacts = []def __init__(self,name='',email='',**kwargs):self.name = 姓名self.email = 电子邮件Contact.all_contacts.append(self)def __str__(self):返回 f'名称为 {self.name},邮件为 {self.mail}.'#父类2:类地址持有者:def __init__(self, street='', city='', state='', code='', **kwargs):self.street = 街道self.city = 城市self.state = 状态self.code = 代码def __str__(self):返回 f'街道是 {self.street},城市是 {self.city},状态是 {self.state},代码是 {self.code}'#Subclass 继承自两个父类:类朋友(联系人,地址持有者):def __init__(self, phone='', **kwargs):self.phone = 电话super().__init__(**kwargs)def __str__(self):return f'''手机是{self.phone}.'''#类的实例f = Friends(phone='aphone', name='aname', mail='amail',street='atreet', city='acity', state='astate', code='acode')打印(f)
这只会打印手机初始化.
尝试这样做,以便打印所有 __str__
,但没有奏效:
def __str__(self):super(Contact.self).__str__()super(AddressHolder.self).__str__()return f'''手机是{self.phone}.'''
最初,我尝试将所有内容放入这样的 Friends
子类中,因为它是继承的,它应该可以工作:
def __str__(self):return f'''手机是{self.phone},街道是{self.street},城市是 {self.city},状态是 {self.state},代码是 {self.code},名字是{self.name},并且邮件是 {self.mail}.'''
但是我得到了一个````AttributeError: 'Friends' object has no attribute 'street'``` 错误(这不是我可以使用父类数据处理子类的继承点吗?).
我给了每个班级他们自己的 __str__
这可以说是糟糕的代码,但也不起作用.
如何打印继承类和子类的所有数据?
如果我收到[子类] 没有属性"错误,继承的限制是什么?
你需要让你的基类协作,让它们同时调用 super().__init__()
:
班级联系人:all_contacts = []def __init__(self, name='', email='', **kwargs):super().__init__(**kwargs)self.name = 姓名self.email = 电子邮件Contact.all_contacts.append(self)
和
类地址持有者:def __init__(self, street='', city='', state='', code='', **kwargs):super().__init__(**kwargs)self.street = 街道self.city = 城市self.state = 状态self.code = 代码def __str__(self):返回 f'街道是 {self.street},城市是 {self.city},状态是 {self.state},代码是 {self.code}'
这是可行的,因为 super()
在 type(self)
方法解析的基类中搜索命名属性(此处为__init__
)Order (MRO),从当前类(定义方法的类)开始.对于 Friends
的实例,MRO 是:
您已经在使用关键字参数来传递额外的参数,因此您将在 MRO 末尾得到一个空的 kwargs
字典,从而有效地调用 object.__init__()
没有参数.
注意你也可以在__str__
方法中使用super()
:
班级联系人:# ...def __str__(self):返回 "\n".join([f'名字是{self.name},邮件是{self.mail}.',super().__str__()])类地址持有者:# ...def __str__(self):返回 "\n".join([f'街道是{self.street},城市是{self.city},'f'状态是{self.state},代码是{self.code}',super().__str__()])类朋友(联系人,地址持有者):# ...def __str__(self):返回 "\n".join([f'电话是{self.phone}.',super().__str__()
这适用于 object
定义的任何属性:
I am currently learning OOP and ran into a problem of dunder methods and inheritance.
I have 2 parent classes (both with their own init) that inherit to a subclass, and i want a string representation of the data initialized in all the classes, together.
This is the problem:
#Parent class 1:
class Contact:
all_contacts = []
def __init__(self,name='',email='',**kwargs):
self.name = name
self.email = email
Contact.all_contacts.append(self)
def __str__(self):
return f'the name is {self.name}, and the mail is {self.mail}.'
#Parent class 2:
class AddressHolder:
def __init__(self, street='', city='', state='', code='', **kwargs):
self.street = street
self.city = city
self.state = state
self.code = code
def __str__(self):
return f'the street is {self.street}, the city is {self.city},
the state is {self.state}, the code is {self.code}'
#Subclass that inherits from both parent classes:
class Friends(Contact, AddressHolder):
def __init__(self, phone='', **kwargs):
self.phone = phone
super().__init__(**kwargs)
def __str__(self):
return f'''The phone is {self.phone}.'''
#The instance of the class
f = Friends(phone='aphone', name='aname', mail='amail',
street='astreet', city='acity', state='astate', code='acode')
print(f)
This will only print phone initialization.
Tried this to make it so all __str__
are printed, but it didn't worked:
def __str__(self):
super(Contact.self).__str__()
super(AddressHolder.self).__str__()
return f'''The phone is {self.phone}.'''
Originally, i tried to put all into the Friends
subclass like this since it was inherited, it should work:
def __str__(self):
return f'''The phone is {self.phone},
the street is {self.street},
the city is {self.city},
the state is {self.state},
the code is {self.code},
the name is {self.name},
and the mail is {self.mail}.'''
But i got a ````AttributeError: 'Friends' object has no attribute 'street'``` error (wasn't the point of inheritance that i could work on the subclass with the parent class data?).
I gave each class their own __str__
which is arguably bad code but doesn't work either.
How can i make print all the data of the inherited classes plus the subclass?
What is the limit of inheritance if i got a "[subclass] has no attribute" error?
You need to make your base classes cooperative, by having them both call super().__init__()
too:
class Contact:
all_contacts = []
def __init__(self, name='', email='', **kwargs):
super().__init__(**kwargs)
self.name = name
self.email = email
Contact.all_contacts.append(self)
and
class AddressHolder:
def __init__(self, street='', city='', state='', code='', **kwargs):
super().__init__(**kwargs)
self.street = street
self.city = city
self.state = state
self.code = code
def __str__(self):
return f'the street is {self.street}, the city is {self.city},
the state is {self.state}, the code is {self.code}'
This works because super()
searches for the named attribute (__init__
here) in the base classes of type(self)
Method Resolution Order (MRO), starting at the current class (the class where the method is defined). For an instance of Friends
, the MRO is:
>>> Friends.__mro__
(<class '__main__.Friends'>, <class '__main__.Contact'>, <class '__main__.AddressHolder'>, <class 'object'>)
You already are using keyword arguments to pass on extra arguments, so you'll end up with an empty kwargs
dictionary at the end of your MRO, effectively calling object.__init__()
with no arguments.
Note that you can also use super()
in the __str__
method:
class Contact:
# ...
def __str__(self):
return "\n".join([
f'the name is {self.name}, and the mail is {self.mail}.',
super().__str__()
])
class AddressHolder:
# ...
def __str__(self):
return "\n".join([
f'the street is {self.street}, the city is {self.city}, '
f'the state is {self.state}, the code is {self.code}',
super().__str__()
])
class Friends(Contact, AddressHolder):
# ...
def __str__(self):
return "\n".join([
f'The phone is {self.phone}.',
super().__str__()
This works for any attribute that object
defines:
>>> print(*dir(object()), sep="\n")
__class__
__delattr__
__dir__
__doc__
__eq__
__format__
__ge__
__getattribute__
__gt__
__hash__
__init__
__init_subclass__
__le__
__lt__
__ne__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__sizeof__
__str__
__subclasshook__
这篇关于继承和dunder方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!