继承和dunder方法? [英] Inheritance and dunder methods?

查看:44
本文介绍了继承和dunder方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在学习 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__(<class '__main__.Friends'>, <class '__main__.Contact'>, <class '__main__.AddressHolder'>, <class 'object'>)

您已经在使用关键字参数来传递额外的参数,因此您将在 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 定义的任何属性:

<预><代码>>>>打印(*dir(object()), sep="\n")__班级____delattr____目录____文档____eq____格式____ge____获取属性____gt____哈希____在里面____init_subclass____le____lt____ne____新的____减少____reduce_ex____repr____setattr____sizeof____str____子类钩子__

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆