web-dev-qa-db-fra.com

Créer une nouvelle instance de classe à partir de la méthode de classe

Je veux pouvoir créer une nouvelle instance d'un objet en appelant une méthode sur un objet déjà instancié. Par exemple, j'ai l'objet:

organism = Organism()

Je veux pouvoir appeler organism.reproduce() et avoir deux objets de type Organism. Ma méthode à ce stade ressemble à ceci:

class Organism(object):
    def reproduce():
        organism = Organism()

et je suis à peu près sûr que cela ne fonctionne pas (je ne sais même pas vraiment comment le tester. J'ai essayé la méthode gc dans ce post ). Alors, comment puis-je faire en sorte que mon objet crée une copie de lui-même accessible comme le premier objet que j'ai créé (avec organism = Organism())?

31
ohblahitsme
class Organism(object):
    def reproduce(self):
        #use self here to customize the new organism ...
        return Organism()

Une autre option - si l'instance (self) n'est pas utilisée dans la méthode:

class Organism(object):
    @classmethod
    def reproduce(cls):
        return cls()

Cela garantit que les organismes produisent plus d'organismes et (les Borgs hypothétiques qui sont dérivés d'organismes produisent plus de Borgs).

Un avantage secondaire de ne pas avoir besoin d'utiliser self est que cela peut maintenant être appelé directement depuis la classe en plus de pouvoir être appelé depuis une instance:

new_organism0 = Organism.reproduce()  # Creates a new organism
new_organism1 = new_organism0.reproduce()  # Also creates a new organism

Enfin, si l'instance (self) et la classe (Organism ou les sous-classes si elles sont appelées à partir d'une sous-classe) sont utilisées dans la méthode:

class Organism(object):
    def reproduce(self):
        #use self here to customize the new organism ...
        return self.__class__()  # same as cls = type(self); return cls()

Dans chaque cas, vous l'utiliseriez comme:

organism = Organism()
new_organism = organism.reproduce()
45
mgilson

Et quelque chose comme ça:

class Organism(object):

    population = []

    def __init__(self, name):
        self.name = name
        self.population.append(self)
    def have_one_child(self, name):
        return Organism(name)
    def reproduce(self, names):
        return [self.have_one_child(name) for name in names]

Résultat:

>>> a = Organism('a')
>>> len(Organism.population)
1
>>> a.reproduce(['x', 'y', 'z']) # when one organism reproduces, children are added
                                 # to the total population
                                 # organism produces as many children as you state
[<__main__.Organism object at 0x05F23190>, <__main__.Organism object at 0x05F230F0>, <__main__.Organism object at 0x05F23230>]
>>> for ele in Organism.population:
...     print ele.name
... 
a
x
y
z
>>> Organism.population[3].reproduce(['f', 'g'])
[<__main__.Organism object at 0x05F231D0>, <__main__.Organism object at 0x05F23290>]
>>> for ele in Organism.population:
...     print ele.name
... 
a
x
y
z
f
g
2
Akavall

pourquoi ne pas simplement utiliser le module de copie?

import copy
organism = Organism()
replica = copy.deepcopy(organism)
1
jcr

De la même manière que vous l'avez fait à l'origine, mais ensuite vous devez en faire quelque chose!

organism = Organism() appelle la classe Organism (les parenthèses directement après un nom sont l'opération "call"). Cela crée et renvoie une nouvelle instance de la classe, que vous liez ensuite au nom organism.

Lorsque vous exécutez cette ligne dans l'interpréteur, vous disposez désormais d'une variable organism faisant référence à la nouvelle instance Organism que vous venez de créer.

Lorsque vous écrivez cette ligne dans une fonction (y compris une méthode, car il n'y a pas de différence entre une méthode et une fonction "de l'intérieur"), cela fait la même chose, mais la variable organism est un local variable. Les variables locales sont supprimées lorsque la fonction est terminée, donc cela fait crée une nouvelle instance de Organism, mais elle n'obtient rien parce que vous n'y avez jamais accès.

Votre fonction doit retourner toute information qu'elle souhaite communiquer à son appelant. Toutes les variables locales que vous ne retournez pas ne sont utiles que si vous utilisez ces variables pour créer quelque chose que vous faites retournez.

Notez que cela a rien à voir avec votre problème particulier de création d'une instance à l'intérieur d'une méthode; c'est juste comment les fonctions/méthodes fonctionnent en général. Vous devrez apprendre le fonctionnement des fonctions avant de pouvoir écrire avec succès des programmes orientés objet à l'aide de classes et d'instances; Je vous suggère fortement de suivre quelques tutoriels.

1
Ben
from copy import copy                                                           

class Organism(object):                                                         

    def __init__(self,name):                                                    
        self.name=name                                                          

    def setName(self,name):                                                     
        self.name=name                                                          

    def reproduce(self,childname):     
        #use deepcopy if necessary                                         
        cp = copy(self)                                                         
        cp.setName("descendant from " + self.name + " " + childname)            
        return cp                                                               

    def __str__(self):                                                          
        return self.name                                                        

first = Organism("first")                                                       
second = first.reproduce("second")                                              

print first                                                                     
print second 
0
RParadox