Проще увидеть, что происходит, если мы исключим магию __bases__
и напишем наши классы, которые вы создаете явно:
class StoryHTMLMixin(object):
def render(self):
return ("<html><title>%s</title>"
"<body>%s</body></html>"
% (self.name, self.content))
class Story(object, StoryHTMLMixin):
def __init__(self, name, content):
self.name = name
self.content = content
Это конечный результат того, что вы делаете - иличто было бы, если бы это удалось.Это приводит к той же ошибке.
Обратите внимание, что это на самом деле не наследование алмазов.Это включает четыре класса, где два базовых класса каждый наследуют общий четвертый класс;Многократное наследование Python справляется с этим.
Здесь у вас есть только три класса, что приводит к наследованию, которое выглядит следующим образом:
StoryHTMLMixin <--- Story
| _____/
| |
v v
object
Python не знает, как решить эту проблему.
Я не знаю, как обойти это.В принципе, решение будет состоять в том, чтобы удалить object
из баз Story
одновременно с добавлением к нему StoryHTMLMixin
, но это не допускается по несколько непрозрачным внутренним причинам (TypeError: __bases__ assignment: 'StoryHTMLMixin' deallocator differs from 'object'
).
Я так или иначе никогда не нашел практического, реального применения для модификации классов.Это просто кажется запутанным и запутанным - если вам нужен класс, производный от этих двух классов, просто создайте класс нормально.
Ed:
Вот подход, который делает нечто похожее на ваше,но без изменения классов на месте.Обратите внимание, как он возвращает новый класс, динамически производный от аргументов функции.Это намного понятнее - вы не можете случайно изменить объекты, которые уже созданы, например.
class Story(object):
def __init__(self, name, content):
self.name = name
self.content = content
class StoryHTMLMixin(object):
def render(self):
return ("<html><title>%s</title>"
"<body>%s</body></html>"
% (self.name, self.content))
def MixIn(TargetClass, MixInClass, name=None):
if name is None:
name = "mixed_%s_with_%s" % (TargetClass.__name__, MixInClass.__name__)
class CombinedClass(TargetClass, MixInClass):
pass
CombinedClass.__name__ = name
return CombinedClass
if __name__ == "__main__":
MixedStory = MixIn(Story, StoryHTMLMixin, "MixedStory")
my_story = MixedStory("My Life", "<p>Is good.</p>")
print my_story.render()