50

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

organism = Organism()

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

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

而且我很确定它不起作用(我什至不确定如何测试它。我在这篇文章中尝试了 gc 方法)。那么如何让我的对象创建一个可访问的自身副本,就像我创建的第一个对象(使用organism = Organism())一样?

4

6 回答 6

81
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()
于 2012-11-06T22:40:00.403 回答
3

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

import copy
organism = Organism()
replica = copy.deepcopy(organism)
于 2012-11-06T22:44:31.177 回答
3

像这样的东西怎么样:

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
于 2012-11-06T23:34:29.393 回答
1

和你最初做的一样,但是你必须用它做点什么!

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

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

当您在函数内部编写该行时(包括方法,因为方法和“从内部”的函数之间没有区别),它做同样的事情,但变量organism局部变量。当函数完成时,局部变量会被丢弃,所以这确实会创建一个新Organism实例,但它不会实现任何目标,因为您永远无法访问它。

您的函数应该返回它想要传达给调用者的任何信息。任何你不返回的局部变量只有在你使用这些变量来创建你确实返回的东西时才有用。

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

于 2012-11-06T22:51:29.147 回答
1

我相信您在问如何复制对象。令人惊讶的是(也许),(几乎)没有标准的方法,这是设计使然。问题来自复制概念的内在模糊性,即:当您复制对象属性时,您的意思是将其复制为引用(复制)还是作为值(深度复制)?

但是,在大多数情况下,您需要一致的行为(所有属性的深拷贝或复制),在这种情况下,您可以将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?

于 2020-01-13T09:48:36.397 回答
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 
于 2012-11-06T22:45:47.193 回答