1

que je cherchais un moyen pour initialiser l'opérateur classe dérivée en utilisant constructeur de copie et() comme en C++Python: l'héritage multiple, constructeur de copie, l'initialisation de la classe et() la surcharge

class Rectangle { 
    int width, height; 
    public: 
    Rectangle (int,int); 
    int area() {return (width*height);} 
}; 

Rectangle::Rectangle (int a, int b) { 
    width = a; 
    height = b; 
} 

r = Rectangle(2,3) 
s = Rectangle(r) /* <--using copy constructor to initialize*/ 

puis je pensais comment pourrais-je mettre en œuvre cette façon de intitialisation au cas où j'ai une classe dérivée des deux autres membres plus de son propre et est venu au-dessous:

class MyBase1(object): 
    def __init__(self, *args, **kwargs): 
     self.x = kwargs.get('x') 
     self.y = kwargs.get('y') 
     print("mybase1 {}".format(kwargs)) 

    def print_base1(self): 
     pass 


class MyBase2(object): 
    def __init__(self, *args, **kwargs): 
     self.s = kwargs.get('s') 
     self.p = kwargs.get('p') 
     print("mybase2 {}".format(kwargs)) 

    def print_base2(self): 
     pass 


class MyChild(MyBase1, MyBase2): 

    def __init__(self, **kwargs): 
     MyBase1.__init__(self, **kwargs) 
     MyBase2.__init__(self, **kwargs) 
     self.function_name = kwargs.get('function') 


    def __call__(self, my_base1, my_base2, **kwargs): 
     initialization_dictionary = dict(vars(my_base1), **vars(my_base2)) 
     initialization_dictionary = dict(initialization_dictionary, **kwargs) 
     newInstance = MyChild(**initialization_dictionary) 
     return newInstance 

appeler alors:

base1 = MyBase1(x=1, y=2) 
base2 = MyBase2(s=3, p=4) 

child = MyChild()(base1, base2, function='arcsine') #<--initialising 

[stm for stm in dir(child) if not stm.startswith('__')] 
# gives:['function_name', 'p', 'print_base1', 'print_base2', 's', 'x', 'y'] 

vars(child) 
# gives:{'function_name': 'arcsine', 'p': 4, 's': 3, 'x': 1, 'y': 2} 

Alors je me demandais par combien c'est de manière non pythonique? Et s'il y a une meilleure façon (ou non) de faire la même chose?

+0

En python, définir un '__copy__' et Méthodes spéciales '__deepcopy__', à utiliser avec les fonctions' copy.copy' et 'copy.deepcopy'. –

+0

Voir, par exemple, [cette question] (http://stackoverflow.com/questions/15684881/python-implementation-of-shallow-and-deep-copy-constructors) –

Répondre

1

Eh bien, vous ne voudriez pas créer une instance pour créer une nouvelle instance, vous voulez probablement un classmethod ou staticmethod. Ce n'est pas l'endroit pour utiliser __call__ non plus.

Je pourrais le faire:

class MyChild(MyBase1, MyBase2): 
    @classmethod 
    def build_from_bases(klass, base1, base2, **kwargs): 
     kwargs.update(base1.__dict__) 
     # Note if base2 has values for x and y, they will clobber what was in base1 
     kwargs.update(base2.__dict__) 
     return klass(**kwargs) 

Mais en utilisant une instance de Base1 et Base2 pour construire une instance de MyChild ne se sent pas comme quelque chose que je ferais en python. Beaucoup plus susceptibles d'utiliser l'évidence:

mychild = MyChild(x=base1.x, y=base1.y, s=base2.s, p=base2.p, function='foo') 

Vraiment, je préférerais que, maintenant, je ne dois pas se préoccuper de valeurs ou autres, en train d'écraser la bizarrerie.

Vous pouvez combiner les deux, si vous voulez vraiment la méthode de coupe courte:

class MyChild(MyBase1, MyBase2): 
    @classmethod 
    def build_from_bases(klass, base1, base2, **kwargs): 
     return klass(x=base1.x, y=base1.y, s=base2.s, p=base2.p, **kwargs) 

vous en python moins « intelligent » est souvent « meilleur »

+0

merci! J'ai eu l'implémentation avec le @classmethod dans mes brouillons, juste essayait en effet de faire "intelligent" avec l'opérateur(), qui est clairement que je vois n'est pas bon. –