从类方法创建新的类实例

时间:2012-11-06 22:38:53

标签: python object copy

我希望能够通过调用已实例化的对象上的方法来创建对象的新实例。例如,我有对象:

organism = Organism()

我希望能够调用organism.reproduce()并拥有两个类型为Organism的对象。我此时的方法如下:

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

并且我很确定它不起作用(我甚至不确定如何测试它。我在this post中尝试了gc方法)。那么如何让我的对象创建一个可以访问的副本,就像我创建的第一个对象一样(使用organism = Organism())?

6 个答案:

答案 0 :(得分:41)

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

另一个选项 - 如果方法中未使用实例(self):

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

这确保了生物体产生更多的生物体和(来自生物体的假想的生物体产生更多的生物体)。

不需要使用self的附带好处是,除了能够从实例调用之外,现在可以直接从类中调用它:

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

最后,如果在方法中使用实例(self)和类(Organism或从子类调用的子类):

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

在每种情况下,您都将其用作:

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

答案 1 :(得分:3)

为什么不简单地使用复制模块?

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

答案 2 :(得分:2)

这样的事情:

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]

结果:

>>> 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

答案 3 :(得分:1)

就像你原来做的那样,但是你必须用它做点什么!

organism = Organism()调用类Organism(名称为“call”操作后直接括号)。这将创建并返回该类的新实例,然后将其绑定到名称organism

当您在解释器中执行该行时,您现在有一个变量organism引用您刚刚创建的新Organism实例。

当你在函数中写入那一行时(包括一个方法,因为方法和函数之间没有“内部”),它会做同样的事情,但变量organism是一个< em> local 变量。函数完成时会丢弃局部变量,因此 会创建一个新的Organism实例,但由于您永远无法访问它,因此无法实现任何目标。

您的函数应返回要与其调用方通信的任何信息。您不返回的任何局部变量仅在您使用这些变量创建返回的内容时才有用。

请注意,这与 nothing 有关于在方法中创建实例的特定问题;它只是函数/方法的一般工作方式。在使用类和实例成功编写面向对象的程序之前,您需要了解函数的工作原理;我强烈建议你完成一些教程。

答案 4 :(得分:0)

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 

答案 5 :(得分:0)

我相信您在问如何复制对象。 令人惊讶的(也许),没有(几乎)没有标准的方法,这是设计使然。问题出在复制概念的内在含混性,即:复制对象属性时,是要复制它作为引用(副本)还是值(深拷贝)?

但是,在大多数情况下,您希望行为一致(对所有属性进行深拷贝或复制),在这种情况下,您可以将copy模块用作

import copy
new_obj = copy.copy(old_obj)

new_obj = copy.deepcopy(old_obj)

在通常情况下,您想要更自定义的行为,则使用相同的命令,但覆盖对象的__copy____deepcopy__方法。

有关详细信息和示例,请参见更多答案,例如: How to override the copy/deepcopy operations for a Python object?