У меня есть класс Parent
. Я хочу определить __new__
для Parent
, так что он немного магии при создании экземпляра (почему, см. Сноску). Я также хочу, чтобы классы детей наследовали этот и другие классы, чтобы получить функции Parent. Parent
__new__
вернет экземпляр подкласса базовых классов дочернего класса и класс Parent
.Python множественное наследование: какой __new__ позвонить?
Это, как будет определен класс ребенок:
class Child(Parent, list):
pass
Но теперь я не знаю, что __new__
позвонить в Parent
«s __new__
. Если я позвоню object.__new__
, приведенный выше пример Child
жалуется, что следует называть list.__new__
. Но как бы Parent
знал это? Я сделал это работа, так что петли через все __bases__
и вызывать каждый __new__
внутри try:
блока:
class Parent(object):
def __new__(cls, *args, **kwargs):
# There is a special wrapper function for instantiating instances of children
# classes that passes in a 'bases' argument, which is the __bases__ of the
# Children class.
bases = kwargs.get('bases')
if bases:
cls = type('name', bases + (cls,), kwargs.get('attr', {}))
for base in cls.__mro__:
if base not in (cls, MyMainType):
try:
obj = base.__new__(cls)
break
except TypeError:
pass
return obj
return object.__new__(cls)
Но это только выглядит как взломать. Наверняка, должен быть лучший способ сделать это?
Спасибо.
- Причины я хочу использовать
__new__
так я могу вернуть объект подкласса, который имеет некоторые динамические атрибуты (магию__int__
атрибутов и т.д.), присвоенные класс. I could have done this in__init__
, но я не смог бы изменитьself.__class__
в__init__
, если новый класс имеет другую внутреннюю структуру, что в данном случае происходит из-за множественного наследования.
У меня был ответ, но потом я понял, что полностью не понял ваш вопрос, поэтому я удалил его, а затем пересмотрел и отменил его. Я думаю, что новый ответ решает вашу проблему и будет работать. Я провел небольшое тестирование. – Omnifarious
Вы отчетливо вписываетесь в метаклассическое программирование, как сложное, так и удивительное. Причина, по которой вы получаете ошибку с __new__, состоит в том, что 'object' и встроенные типы, такие как' list' и 'dict', а также объекты с' __slots__' имеют разные макеты памяти. Более глубокое понимание того, что вы пытаетесь выполнить, поможет многое. Вы также можете посмотреть на использование декоратора класса или функции в слоте __metaclass__. –
Я не уверен, почему вам нужно будет изменить себя .__ class__, вы не упомянули об этом. И если вам нужно сделать сложную магию, как это в __new__, одно решение, которое часто намного проще, - это не делать этого вообще, а вместо этого использовать фабрику. –