Наследование и дурные методы? - PullRequest
0 голосов
/ 19 января 2020

В настоящее время я изучаю OOP и столкнулся с проблемой более сложных методов и наследования.

У меня есть 2 родительских класса (оба с собственным init), которые наследуются подклассу, и я хочу строку представление данных, инициализированных во всех классах, вместе.

Это проблема:

#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)

Это будет печатать только инициализацию телефона.

Попытался сделать это, чтобы сделать это поэтому все __str__ напечатаны, но это не сработало:


    def __str__(self):
        super(Contact.self).__str__()
        super(AddressHolder.self).__str__()
        return f'''The phone is {self.phone}.'''

Первоначально я пытался поместить все в подкласс Friends, как это, так как он был унаследован, он должен работать:

    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}.'''

Но я получил ошибку `` `` AttributeError: 'Friends' не имеет атрибута 'street'``` (не было той точки наследования, что я мог работать на подклассе с родительским классом данные?).

Я дал каждому классу свой собственный __str__, что, возможно, является плохим кодом, но тоже не работает.

Как я могу напечатать все данные унаследованных классов плюс подкласс?

Каков предел наследование, если я получил ошибку «[подкласс] не имеет атрибута»?

Ответы [ 2 ]

2 голосов
/ 20 января 2020

Вы должны сделать свои базовые классы совместными, заставив их обоих также вызвать super().__init__():

class Contact:

    all_contacts = []

    def __init__(self, name='', email='', **kwargs):
        super().__init__(**kwargs)
        self.name = name
        self.email = email
        Contact.all_contacts.append(self)

и

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}'

Это работает, потому что super() ищет именованный атрибут (__init__ здесь) в базовых классах type(self) Порядок разрешения методов (MRO), начиная с текущего класса (класса, в котором определен метод). Для экземпляра Friends MRO:

>>> Friends.__mro__
(<class '__main__.Friends'>, <class '__main__.Contact'>, <class '__main__.AddressHolder'>, <class 'object'>)

Вы уже используете аргументы ключевого слова для передачи дополнительных аргументов, поэтому в конце вы получите пустой словарь kwargs в конце ваше MRO, фактически вызывающее object.__init__() без аргументов.

Обратите внимание, что вы также можете использовать super() в методе __str__:

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__()

Это работает для любого атрибута, object определяет:

>>> 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__
1 голос
/ 20 января 2020

Вы можете попробовать сделать что-то вроде этого:

class A:
    def __init__(self, a):
        self.a = a

    def __str__(self):
        return self.a

class B:
    def __init__(self, b):
        self.b = b

    def __str__(self):
        return self.b

class C(A, B):
    def __init__(self, a, b, c):
        A.__init__(self, a)
        B.__init__(self, b)
        self.c = c

    def __str__(self):
        return A.__str__(self) + B.__str__(self) + self.c

c = C("a", "b", "c")
print(c)

Это выведет abc. Просто замените a, b и c на нужные значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...