Страницы

Поиск по вопросам

суббота, 15 июня 2019 г.

Инициализация атрибутов базовых классов при множественном наследовании

Не могу разобраться до конца в классах Python. Задаю объекты:
p1 = Point(50,70) # объект класса Point, задающий начальную координату c1 = Color(10,15,10) # задает цвет r1 = Rectangle(p1,40,70,c1) #в нем и загвоздка, а точнее в p1 и c1
Как сделать так, чтобы r1 имел также аргументы x и y и r,g,b, которые имеют p1 и c1 соответственно.
!!! в моем классе Rectangle self.pointIn = pointIn и self.color = color явно заданы неправильно
class Point(object): def __init__(self,x=0, y=0): self.x = x self.y = y
def modify_point(self, x1,y1): self.x = x1 self.y = y1
def to_tuple(self): return (self.x, self.y)
class Color(object): def __init__(self,r=0, g=0, b=0): self.r = r self.g = g self.b = b
def to_tuple(self): return (self.r, self.g, self.b)
class Rectangle(Point, Color): def __init__(self, pointIn, width, hight, color): self.width = width self.hight = hight self.pointIn = pointIn self.color = color


Ответ

Прямоугольник может иметь цвет. Прямоугольник сам по себе цветом не является. То есть логичнее использовать: rectangle.color.r вместо rectangle.r и не наследовать от Color (тем более вы уже используете композицию: self.color определён).
Как сделать так, чтобы r1 имел также аргументы x и y и r,g,b, которые имеют p1 и c1 соответственно.
Если забыть, что это прямоугольники, точки, цвета и рассматривать задачу как упражнение по использованию множественного наследования (которое следует избегать, если вы не знаете точно зачем оно вам нужно в конкретном случае), то чтобы правильно проинициализировать унаследованные атрибуты базовых классов, необходимо вызывать super().__init__(**kwargs)
#!/usr/bin/env python3
class A: def __init__(self, a, **kwargs): super().__init__(**kwargs) self.a = a
def __repr__(self): keys = sorted(self.__dict__) items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys) return "{}({})".format(type(self).__name__, ", ".join(items))
class B: def __init__(self, b, **kwargs): super().__init__(**kwargs) self.b = b
class C(A, B): def __init__(self, c, **kwargs): super().__init__(**kwargs) self.c = c
print(C(a=1, b=2, c=3))
super().__init__() вызов только один в C.__init__(), не смотря на то что C имеет два базовых класса.
A.__init__() и B.__init__() существуют и также вызывают super().__init__() и все эти методы имеют совместимые аргументы (за счёт **kwargs). См. Python’s super() considered super!
__repr__ метод (с реализацией из документации types.SimpleNamespace) определён, чтобы напечатать C объект. Вывод показывает, что все атрибуты правильно установлены.
Ключевое понятие здесь—порядок разрешения методов (MRO)—порядок, в котором вызываются методы базовых классов:
>>> [klass.__name__ for klass in C.mro()] ['C', 'A', 'B', 'object']
С.__init__ ожидаемо вызывает родительский A.__init__ (через super().__init__()). A класс не наследует от B, но A.__init__ вызывает (через super().__init__()) B.__init__ согласно MRO, который вызывает object.__init__ и цепочка заканчивается.
object встречается в этом списке только один раз, хотя он является базовым классом как для A так и B классов (то есть C наследует от object класса дважды). Чтобы вычислить порядок вызовов, в Питоне используется C3-линеаризация суперкласса

Комментариев нет:

Отправить комментарий