如何解决Python 迭代器类始终返回字典对象的初始状态为什么?
class C:
def __init__(self):
self.ii={ 'c':0,'t':"kkk" }
def __iter__(self):
return self
def __next__(self):
if self.ii['c']>5:
self.ii['c']=0
raise stopiteration
self.ii['c']+=1
print(self.ii)
return self.ii
x=C()
for i in x:
pass
print([i for i in x])
我想,print([i ...])
会在“c”字段中显示一个值越来越大的列表。但是它显示了初始 { 'c':0,'t': 'kkk' } 的六个片段。
好的,我知道,我可以通过将 .copy()
添加到 return self.ii
来使其工作,但我想知道,当没有 copy() 时会发生什么。
如果它给我一个带有 { 'c':6,'t':'kkk' }
的列表,我可以接受,因为字典是按地址处理的,而不是按值处理的,但这...我无法理解。
解决方法
您使用理解语句构建的列表包含对同一字典 (x.ii) 的六个引用。它不是“原始”字典,而是 __next__
将 self.ii['c']
重置为 0
之后的字典。
如果您的列表推导式在重置之前捕获了 i['c']
的值,您将获得不同的值:
>>> print([i['c'] for i in x])
[1,2,3,4,5,6]
您可以通过更改其中一个来观察原始列表推导式捕获六个相同引用的问题:
>>> y = [i for i in x]
>>> y[0]['test'] = 'foobar'
>>> y[1]['c'] = 42
>>> x.ii
{'c': 42,'t': 'kkk','test': 'foobar'}
>>> y
[{'c': 42,'test': 'foobar'},{'c': 42,'test': 'foobar'}]
正如您所观察到的,更改 __next__
以返回字典的副本而不是共享引用使得这种情况不可能发生。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。