Python类实例具有浅层连接的问题
我试图用Python编写一个遗传算法框架,但遇到了浅/深复制的问题。我的背景主要是C/C++,我很难理解这些连接是如何持久的 我看到的是子类中属性列表长度的爆炸。我的代码如下……我会指出问题所在 这是一个单一基因的类别。本质上,它应该有一个名称、值和布尔标志。Python类实例具有浅层连接的问题,python,python-2.7,deep-copy,shallow-copy,Python,Python 2.7,Deep Copy,Shallow Copy,我试图用Python编写一个遗传算法框架,但遇到了浅/深复制的问题。我的背景主要是C/C++,我很难理解这些连接是如何持久的 我看到的是子类中属性列表长度的爆炸。我的代码如下……我会指出问题所在 这是一个单一基因的类别。本质上,它应该有一个名称、值和布尔标志。Gene的实例填充myIndividual类中的列表 # gene class class Gene(): # constructor def __init__(self, name, is_float): self.nam
Gene
的实例填充myIndividual
类中的列表
# gene class
class Gene():
# constructor
def __init__(self, name, is_float):
self.name_ = name
self.is_float_ = is_float
self.value_ = self.randomize_gene()
# create a random gene
def randomize_gene(self):
return random.random()
这是我的个人课程。每一代都会创建一个群体(我将在类声明后显示创建代码),并应用典型的遗传算法操作。值得注意的是print len(self.Genes)
调用,每次实例化这个类时它都会增长
# individual class
class Individual():
# genome definition
Genes_ = [] # genes list
evaluated_ = False # prevent re-evaluation
fitness_ = 0.0 # fitness value (from evaluation)
trace_ = "" # path to trace file
generation_ = 0 # generation to which this individual belonged
indiv_ = 0 # identify this individual by number
# constructor
def __init__(self, gen, indv):
# assign indices
self.generation_ = gen
self.indiv_ = indv
self.fitness_ = random.random()
# populate genome
for lp in cfg.params_:
g = Gene(lp[0], lp[1])
self.Genes_.append(g)
print len(self.Genes_)
> python ga.py
> 24
> 48
> 72
> 96
> 120
> 144
......
正如你所看到的,每个人都应该有24个基因,然而这个群体爆炸得相当快。
我创建了一个新个体的初始群体,如下所示:
# create a randomized initial population
def createPopulation(self, gen):
loc_population = []
for i in range(0, cfg.population_size_):
indv = Individual(gen, i)
loc_population.append(indv)
return loc_population
后来在我的主循环中(为整个转储道歉,但觉得这是必要的-如果需要我的辅助调用(变异/交叉),请让我知道))
我不完全确定我是否理解您的问题,但我怀疑您的问题在于,您的单个()类中的Genes_uu变量是在类名称空间中声明的。该名称空间可用于该类的所有成员。换句话说,Individual()的每个实例将共享相同的变量
考虑以下两个片段:
class Individual():
# genome definition
genes = []
def __init__(self):
for i in xrange(10):
self.genes.append(i)
ind_1 = Individual()
print ind_1.genes
ind_2 = Individual()
print ind_1.genes
print ind_2.genes
及
第一个代码段输出
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
而第二个代码段输出
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
在第一个场景中,当第二个个体()被实例化时,genes list变量已经存在,并且来自第二个个体的基因被添加到此现有列表中
而不是像这样创建单个()类
# individual class
class Individual():
# genome definition
Genes_ = [] # genes list
# constructor
def __init__(self, gen, indv):
# assign indices
self.generation_ = gen
self.indiv_ = indv
self.fitness_ = random.random()
你应该考虑在<强> init <强>中声明GeNeSyz变量,以便每个个体(实例)得到其自己的基因集
# individual class
class Individual():
# constructor
def __init__(self, gen, indv):
# genome definition
self.Genes_ = [] # genes list
# assign indices
self.generation_ = gen
self.indiv_ = indv
self.fitness_ = random.random()
当你创建一个类时,你实际上只创建了一个“类对象”。这些对象与Python中的任何其他对象一样;Python中的一切都是一个对象,这些对象所做的是由它们的方法定义的,而不是它们的类!这就是鸭子打字的神奇之处。在Python中,您甚至可以动态创建新类
无论如何,您只需要将一个列表对象添加到一个且唯一的“个人”类对象的“基因”属性中。结果是“单个”类对象的每个实例对象都在访问相同的“基因”列表对象
想想这个
# In 2.2 <= Python < 3.0 you should ALWAYS inherit from 'object'.
class Foobar(object):
doodah = []
a = Foobar()
b = Foobar()
assert id(a.doodah) == id(b.doodah) # True
class Foobar(object):
doodah = []
a = Foobar()
b = Foobar()
a.doodah = 'hlaghalgh'
assert id(a.doodah) != id(b.doodah) # True
在这种情况下,它们是不同的对象
有可能既吃蛋糕,又吃蛋糕。考虑这个
# In 2.2 <= Python < 3.0 you should ALWAYS inherit from 'object'.
class Foobar(object):
doodah = []
a = Foobar()
b = Foobar()
assert id(a.doodah) == id(b.doodah) # True
class Foobar(object):
doodah = []
a = Foobar()
b = Foobar()
a.doodah = 'hlaghalgh'
assert id(a.doodah) != id(b.doodah) # True
在这种情况下,“doodah”属性被添加到“a”对象中,该对象将覆盖class属性
希望这有帮助 你是一位绅士和学者。我不知道如果不是赛尔夫。那不是本地的。谢谢