Python类实例具有浅层连接的问题

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

我试图用Python编写一个遗传算法框架,但遇到了浅/深复制的问题。我的背景主要是C/C++,我很难理解这些连接是如何持久的

我看到的是子类中属性列表长度的爆炸。我的代码如下……我会指出问题所在

这是一个单一基因的类别。本质上,它应该有一个名称、值和布尔标志。
Gene
的实例填充my
Individual
类中的列表

# 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属性


希望这有帮助

你是一位绅士和学者。我不知道如果不是赛尔夫。那不是本地的。谢谢