Python生成器vs理解并通过引用传递vs值

时间:2014-11-20 07:51:42

标签: python oop list-comprehension

我有一些迭代字符串的代码,并从字符串中生成一个对象列表,我称之为实例。它看起来像这样。

from collections import defaultdict

class MyInstance:
    data = defaultdict(str)

    def __init__(self, data, parser):
        # parse the input
        self.parser = parser


class MyParser:
    def __init__(self, data):
        self.data = data
        data = data.split('\n\n')
        self.instances = (MyInstance(instance, self) for instance in data)


mydata = # ... coming in from stdin or file
parser = MyParser(mydata)

这工作正常,但后来我意识到我需要不止一次检查我的实例。所以,我想我只是将我的生成器改为列表理解:

self.instances = [MyInstance(instance, self) for instance in data]

这允许我根据需要多次迭代我的实例,但突然之间,所有实例都是相同的。当我在此行之前打印出数据时,每个实例都是唯一的。但是,在列表理解之后,它们都是一样的。

class MyParser:
    def __init__(self, data):
        self.data = data
        data = data.split('\n\n')
        print data
        self.instances = (MyInstance(instance, self) for instance in data)
        print list(self.instances)

...打印

['the soldier sleeps', 'the big soldier sleeps', 'the big wonderful soldier sleeps']
['the big wonderful soldier sleeps', 'the big wonderful soldier sleeps', 'the big wonderful soldier sleeps']

然而,最奇怪的是,当我尝试使用与上述类似的代码重新创建此问题时,我无法复制它

class myClass:

  def __init__(self, i):
    self.i = i

  def __repr__(self):
    return self.__str__()

  def __str__(self):
    return str(self.i)


instances = [myClass(i) for i in range(3)]
print instances

instances = (myClass(i) for i in range(3))
print list(instances)

...打印

[0, 1, 2]
[0, 1, 2]

我检查了每个实例的内存地址(在破碎的代码中)是相同还是不同,看起来它们是不同的......(虽然我承认我不确定这是否意味着任何东西)

for i in self.instances:
  print id(i) # 4463026760, 4463026544, 4463026616

所以,我不知道发生了什么。关于为什么这些实例似乎有联系的任何建议?

1 个答案:

答案 0 :(得分:0)

似乎问题与我如何启动数据有关。我作为班级成员发起了一个defaultdict:

class myClass:
    self.data = defaultdict(str)

    def __init__(self, data):
        for i, instance in enumerate(data.split('\n')):
            # Do something...
            self.data[i] = instance

我把它更改为:

class myClass:

    def __init__(self, data):
        self.data = defaultdict(str)
        for i, instance in enumerate(data.split('\n')):
            # Do something...
            self.data[i] = instance

这解决了我的问题。有兴趣听听是否有人知道原因。