I want to be able to create a new instance of an object by calling a method on an already instantiated object. For example, I have the object:
organism = Organ
I believe you are asking how to copy an object. Surprisingly (maybe), there is (almost) no standard method for this, and this is by design. The issue comes from the intrinsic ambiguity of the idea of copying, i.e.: when you copy an object property do you mean to copy it as reference (copy) or as value (deepcopy)?
However, in the majority of cases you want a consistent behavior (deepcopy or copy for all properties), in this case you can use copy
module as
import copy
new_obj = copy.copy(old_obj)
or
new_obj = copy.deepcopy(old_obj)
In a generic case in which you want a more customized behavior, you use the same commands, but override the __copy__
and __deepcopy__
methods of your objects.
See more answers for details and examples, e.g.: How to override the copy/deepcopy operations for a Python object?
What about something like this:
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]
Result:
>>> 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
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
class Organism(object):
def reproduce(self):
#use self here to customize the new organism ...
return Organism()
Another option -- if the instance (self
) isn't used within the method:
class Organism(object):
@classmethod
def reproduce(cls):
return cls()
This makes sure that Organisms produce more Organisms and (hypothetical Borgs which are derived from Organisms produce more Borgs).
A side benefit of not needing to use self
is that this can now be called from the class directly in addition to being able to be called from an instance:
new_organism0 = Organism.reproduce() # Creates a new organism
new_organism1 = new_organism0.reproduce() # Also creates a new organism
Finally, if both the instance (self
) and the class (Organism
or subclasses if called from a subclass) are used within the method:
class Organism(object):
def reproduce(self):
#use self here to customize the new organism ...
return self.__class__() # same as cls = type(self); return cls()
In each case, you'd use it as:
organism = Organism()
new_organism = organism.reproduce()
The same way you did originally, but then you have to do something with it!
organism = Organism()
calls the class Organism
(parentheses directly after a name is the "call" operation). This creates and returns a new instance of the class, which you then bind to the name organism
.
When you execute that line in the interpreter, you now have a variable organism
referring to the new Organism
instance you just created.
When you write that line inside a function (including a method, because there's no difference between a method and a function "from the inside"), it does the same thing, but the variable organism
is a local variable. Local variables are thrown away when the function is finished, so this does create a new Organism
instance, but it doesn't achieve anything because you never gain access to it.
Your function should return any information it wants to communicate to its caller. Any local variables that you don't return are only useful if you use those variables to create something you do return.
Note that this has nothing to do with your particular problem of creating an instance inside a method; it's just how functions/methods work in general. You will need to learn how functions work before you can successfully write object-oriented programs using classes and instances; I would strongly suggest you work through some tutorials.
why not simply use the copy module?
import copy
organism = Organism()
replica = copy.deepcopy(organism)