Лучший способ решения проблемы с алмазами в Python с полямиPython

Программы на Python
Гость
Лучший способ решения проблемы с алмазами в Python с полями

Сообщение Гость »


Python хорошо решает проблему ромба, если в классах нет полей, путем линеаризации порядка разрешения метода. Однако если в классах есть поля, как вызвать суперконструкторы? Подумайте:

Код: Выделить всё

class A:
def __init__(self, a):
self.a = a  # Should only be initialized once.

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

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

class D(C, B):
def __init__(self, a, b, c):
super().???  # What do you put in here.
Для моего варианта использования у меня действительно есть решение, потому что b не может иметь значение None в приложении, и поэтому в основном работает следующее:

Код: Выделить всё

class A:
def __init__(self, a):
self.a = a  # Should only be initialized once.

class B(A):
def __init__(self, a, b):
assert b is not None  # Special case of `b` can't be `None`.
super().__init__(a)
self.b = b

class C(A):
def __init__(self, a, c, b=None):  # Special init with default sentinel `b`.
if b is None:
super().__init__(a)  # Normally `C`'s super is `A`.
else:
super().__init__(a, b)  # From `D` though, `C`'s super is `B`.
self.c = c

class D(C, B):  # Note order, `C`'s init is super init.
def __init__(self, a, b, c):
super().__init__(a, c, b)

def main():
A('a')
B('b', 1)
C('c', 2)
D('d', 3, 4)
C('c2', 5, 6)  # TypeError: __init__() takes 2 positional arguments but 3 were given
Это в основном работает для особого случая, когда b не может быть None, однако все равно возникает проблема, если C __init__< /code> вызывается напрямую (см. последнюю строку выше). Также вам необходимо изменить C для множественного наследования и наследовать в порядке C, B.
==== Изменить ===< /p>
Другая возможность — вручную инициализировать каждое поле (это чем-то похоже на то, как Scala обрабатывает скрытые поля).

Код: Выделить всё

class A0:
def __init__(self, a):  # Special separate init of `a`.
self._init_a(a)

def _init_a(self, a):
self.a = a

class B0(A0):
def __init__(self, a, b):  # Special separate init of `b`.
self._init_a(a)
self._init_b(b)

def _init_b(self, b):
self.b = b

class C0(A0):
def __init__(self, a, c):  # Special separate init of `c`.
self._init_a(a)
self._init_c(c)

def _init_c(self, c):
self.c = c

class D0(C0, B0):
def __init__(self, a, b, c):  # Uses special separate inits of `a`, `b`, and `c`.
self._init_a(a)
self._init_b(b)
self._init_c(c)
The disadvantage of this approach is that it is very non-standard, to the extent that PyCharm gives a warning about not calling super init.
==== End edit ===
Is there a better way?
Thanks in advance for any help, Howard.


Источник: https://stackoverflow.com/questions/662 ... ith-fields

Вернуться в «Python»