python - 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' }
,因为字典是按地址处理的,而不是按值处理的,但是这个......我不明白。
解决方案
您使用理解语句构建的列表包含对同一 dict (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, 't': 'kkk', 'test': 'foobar'}, {'c': 42, 't': 'kkk', 'test': 'foobar'}, {'c': 42, 't': 'kkk', 'test': 'foobar'}, {'c': 42, 't': 'kkk', 'test': 'foobar'}, {'c': 42, 't': 'kkk', 'test': 'foobar'}, {'c': 42, 't': 'kkk', 'test': 'foobar'}]
正如您所观察到的,将您更改__next__
为返回 dict 的副本而不是共享引用使得这种情况不可能发生。
推荐阅读
- python - 如何在条件匹配三行的情况下遍历熊猫数据框中的选定行?
- laravel - Maatwebsite/Laravel-Excel Import 将特殊字符转换为数字 0
- vb.net - 检查 VB.NET 中值类型的空值
- python - 如何在 django 中检查 BASE_DIR?
- angular - 在您手动单击选项卡之前,不会出现异步管道和按钮
- arrays - 如何在 ejs 模板中使用数组显示来自 mongo 的 json 数据?
- powerbi - 计算 DAX 中过去 5 天的重复值
- java - 当 Files.move() 失败时会发生什么?
- elasticsearch - 弹性搜索节点之一继续进入错误状态
- math - 连分数和 Pell 方程 - 数值问题