2010-01-08 4 views
0

Basé sur this answer, de la façon dont __new__ et __init__ sont censés travailler en Python,Héritage multiple Python: Quel est le problème de le faire dynamiquement?

j'ai écrit ce code pour définir dynamiquement et créer une nouvelle classe et de l'objet.

class A(object): 
    def __new__(cls): 
     class C(cls, B): 
      pass 
     self = C() 
     return self 

    def foo(self): 
     print 'foo' 

class B(object): 
    def bar(self): 
     print 'bar' 

a = A() 
a.foo() 
a.bar() 

Fondamentalement, parce que le __new__ de A renvoie un C créé dynamiquement qui hérite A et B, il doit avoir un attribut bar.

Pourquoi Cet non ont un attribut bar?

+0

Quelle est la question? –

+0

D'après quelle réponse? Vous manquez un lien? –

+0

Roger, Dominic, Yup le lien était manquant. Maintenant mis à jour la question, de manière appropriée. –

Répondre

7

Resolve la récursion infinie:

class A(object): 
    def __new__(cls): 
    class C(cls, B): 
     pass 
    self = object.__new__(C) 
    return self 

(Merci à balpha d'avoir signalé la question réelle.)

3

Si votre question est « Comment puis-je accomplir cela » – cela fonctionne:

class A(object): 
    @classmethod 
    def get_with_B(cls): 
     class C(B, cls): 
     pass 

     return C() 

    def foo(self): 
     print 'foo' 

class B(object): 
    def bar(self): 
     print 'bar' 

a = A.get_with_B() 
a.foo() 
a.bar() 

Si votre question est « Pourquoi ça ne marche pas » – qui est parce que vous exécutez dans une récursion infinie lorsque vous appelez C(), ce qui conduit à A.__new__ appelé, qui appelle à nouveau C() etc.

7

Comme il n'y a pas réelle question dans la question, je vais t Ake it littéralement:

Quel est le problème de le faire dynamiquement?
Eh bien, il est pratiquement illisible, extrêmement opaque et non évident pour l'utilisateur de votre code (cela vous inclut dans un mois: P). De mon expérience (assez limitée, je dois admettre, malheureusement je n'ai pas 20 ans de programmation sous la ceinture), un besoin de telles solutions indique, que la structure de classe n'est pas bien définie, - signifie, il y a presque toujours une façon meilleure, plus lisible et moins mystérieuse de faire de telles choses. Par exemple, si vous vraiment souhaitez définir des classes de base à la volée, il est préférable d'utiliser une fonction usine, qui renverra les classes appropriées en fonction de vos besoins.

Une autre prise sur la question:
Quel est le problème de le faire dynamiquement?
Dans votre implémentation actuelle, il me donne une erreur "profondeur de récursivité maximale dépassée". Cela se produit, car A.__new__ s'auto-appelle de lui-même indéfiniment (puisqu'il hérite de lui-même et de B).

10: A l'intérieur A.__new__, "cls" est défini sur <class '.A'>. A l'intérieur du constructeur, vous définissez une classe C, qui hérite de cls (qui est actuellement A) et une autre classe B. Lors de l'instanciation C, son __new__ est appelée. Comme il ne définit pas son propre __new__, sa classe de base '__new__ est appelée. La classe de base se trouve être A.
20: GOTO 10