Я нахожусь в странной ситуации наследования алмазов, еще хуже то, что классы в середине алмаза делят члена. Ниже я продемонстрировал фрагмент кода, который подчеркивает мою проблему.
Метод, который я использовал при написании классов, я узнал от http://rhettinger.wordpress.com/2011/05/26/super-considered-super/, который связан на сайте документации по Python для встроенной функции super
class A(object):
pass
class B(A):
def __init__(self, z=None, **kwargs):
self.z = z
super(B, self).__init__(**kwargs)
# super(B, self).__init__(z=z, **kwargs)
class C(A):
def __init__(self, z=None, **kwargs):
self.z = z
super(C, self).__init__(**kwargs)
class D(B, C):
pass
d = D(z='y')
for arg, value in d.__dict__.iteritems():
print arg, ':', value
, который дает вывод
z : None
Проблема в том, что метод использования аргументов ключевых слов для обеспечения соответствия сигнатур функций убирает аргумент z из вызова инициализации класса C. Я могу принудительно добавить аргумент обратно в kwargs (см. Закомментированный код), но тогда это приводит к тому, что я не могу создать экземпляр объекта типа B, так как это приведет к вызову init объекта, который не принимает параметров, это хорошая функция, потому что она не позволяет мне вводить недопустимые аргументы при создании любого из объектов ниже.
Также я заметил, что если у меня есть строка super, прежде чем я установлю переменные, тогда проблема будет решена, так как объект самого высокого уровня перезапишет нижние уровни. Однако мой код в значительной степени построен на конце super, так как все фактические «установки» выполняются низкоуровневыми классами, тогда как классы более высокого уровня передают значение, которое устанавливается в цепочке наследования. Существуют ли инструкции о том, где вписаться в родительские вызовы?
Есть идеи Stackoverflow?
спасибо
p.s. Это просто плохой дизайн «кооперативных классов»? Что такое кооперативный класс? Есть ли правила или рекомендации, которым нужно следовать?
редактирование:
Stackoverflow не позволит мне ответить на мой собственный вопрос, но я нашел решение.
Я не думаю, что должны быть какие-либо общие члены между кооперативными классами. Если когда-либо существуют два класса, которые не зависят друг от друга (в том смысле, что нет отношения типа «это своего рода»), которые разделяют члена, то вам следует добавить уровень абстракции в отношение наследования.
Общий член должен быть извлечен и помещен в отдельный класс, который наследуется от общего базового класса и наследуется классами в ромбе.
Ниже приведен исправленный код. В соответствии со ссылкой в OP я ввел базовый класс Root
Я должен отметить, что у меня не было формального образования в области программирования (как и большинство здесь, я думаю), поэтому извиняюсь, если я использую неправильную терминологию.
class Root(object):
pass
class A(Root):
pass
class HasAZ(Root):
def __init__(self, z=None, **kwargs):
self.z = z
super(HasAZ, self).__init__(**kwargs)
class B(HasAZ, A):
pass
class C(HasAZ, A):
pass
class D(B, C):
pass
d = D(z='y')
for arg, value in d.__dict__.iteritems():
print arg, ':', value