对Python可迭代对象的误解

对Python可迭代对象的误解,第1张

问题由来: 我之前一直以为可迭代对象生成后就不会受到创建时参数的影响
例如:

n = 3
lst = range(n)  # 后面n的改变并不会影响这个已经生成的可迭代对象
n = n - 1
print(lst) #>>range(0,3)

但是今天写代码时发现当创建可迭代对象包含其他可迭代对象时是会收到影响的。
按我之前的理解,当csv.reader返回一个可迭代对象后,之后再对文件指针做出改变后应该不会影响这个可迭代对象。但是结果和我想的并不一样,read之后文件指针指向了末尾,此时用for i 去迭代是迭代不出来的,并需要还要再设置文件指针到开头才能迭代出来。



在请教了高天大神后,他给出的回答

在这里的csv.reader确实是返回了一个可迭代对象(并且它是一个迭代器),但这个迭代器保存着一个csvfile(file同样也是一个可迭代对象),当每次从这个可迭代对象(即lst)取值时,都会首先读这个csvfile这个对象

所以可迭代对象并不是都不会受其他因素的影响,range确实不会,但很多都会,举个简单的例子创建一个生成器

lst = [0,1,2]
gen = (i for i in lst)
lst.append(3)
print(list(gen))

后面想想好像会对可迭代产生的影响首先必须是序列其次还得是可变对象
为什么必须是序列:因为迭代器本身就是一个有序的序列,只是我们不知道这个序列的长度,通过不断调用next()函数计算下一个数据,因此会对迭代器产生影响的可迭代对象其也必须具有序的概念,这也是为什么传入set并改变元素会报错而list不会,因为set中元素的顺序是根据hash计算得来的,增加一个新的元素可能会使元素顺序发生改变

A set is backed by a hash table (see Why is the order in Python dictionaries and sets arbitrary?). Entries in the set are slotted in to that table based on their hash, which in turn determines their order.
Adding or removing items to that hash table will alter the iteration order, sometimes materially as the table can be re-sized (where all existing entries are re-slotted based on the new table size). Because of this iteration can’t continue the moment the set has been altered; you’d otherwise are liable to see the same values again, even in a different order.
Lists, on the other hand, have a well-defined ordering. Inserting or deleting items can alter that order, but in a well-defined way. A list iterator thus simply can use an ever-increasing index to find a ‘next’ item, until that index matches the current list length.

lst = {1,3,2}
gen = (i for i in lst)
lst.add(0)
print(set(gen))  #>>会报错,提示:Set changed size during iteration

为什么是可变对象很好理解,因为如果不是可变对象,只要值改变了便用引用的对象地址也就改变了

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/730914.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存