J'ai une classe Parent
. Je veux définir un __new__
pour Parent
donc ça fait un peu de magie à l'instanciation (pour pourquoi, voir note de bas de page). Je souhaite également que les classes enfants héritent de cette classe et d'autres classes pour obtenir les fonctionnalités de Parent. La __new__
de retournera une instance d'une sous-classe des bases de la classe enfant et de la classe Parent
.Héritage multiple Python: quel __new__ appeler?
C'est la façon de définir la classe enfant:
class Child(Parent, list):
pass
Mais maintenant, je ne sais pas ce que __new__
pour appeler à l » __new__
Parent
. Si j'appelle object.__new__
, l'exemple Child
ci-dessus se plaint que list.__new__
devrait être appelé. Mais comment le Parent
le sait-il? Je l'ai fait le travail il boucle à travers tous les __bases__
, et appelle chaque __new__
dans un bloc 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)
Mais cela ressemble comme un hack. Sûrement, il doit y avoir une meilleure façon de faire cela?
Merci.
- La raison pour laquelle je veux utiliser
__new__
est pour que je puisse retourner un objet d'une sous-classe qui a des attributs dynamiques (la magie__int__
attributs, etc.) affectés à la classe. Je could have done this in__init__
, mais je ne serais pas en mesure de modifierself.__class__
en__init__
si la nouvelle classe a une structure interne différente, ce qui est le cas ici en raison de l'héritage multiple.
J'ai eu une réponse, mais je me suis rendu compte que j'avais totalement mal compris votre question, alors je l'ai supprimé et ensuite l'ai révisé et supprimé. Je pense que la nouvelle réponse répond à votre problème et fonctionnera. J'ai fait quelques tests minimes. – Omnifarious
Vous êtes distinctement dans le domaine de la programmation de métaclasses, à la fois difficile et merveilleux. La raison pour laquelle vous obtenez l'erreur avec __new__ est que les objets 'object' et builtin comme' list' et 'dict', ainsi que les objets avec' __slots__' ont des configurations de mémoire différentes. Plus de perspicacité dans ce que vous essayez d'accomplir aiderait beaucoup. Vous pouvez également utiliser un décorateur de classe ou une fonction dans l'emplacement __metaclass__. –
Je ne sais pas pourquoi vous devriez modifier self .__ class__, vous ne le mentionnez pas. Et si vous avez besoin de faire de la magie compliquée comme ceci dans __new__, une solution qui est souvent beaucoup plus facile est de ne pas le faire du tout, mais d'utiliser une usine. –