我已经如下尝试了列表和生成器:
lst = list('12345')
def get_generator(lst):
yield from lst
gen_on_lst = get_generator(lst)
lst.append('6') # you can try remove as well
print(list(gen_on_lst))
输出是['1', '2', '3', '4', '5', '6']
,这是我所期望的,因为您需要使用循环或类似的东西来消耗生成器以使其实际执行,并且显然生成器已“链接”到此处的列表并在列表上进行更改影响发电机。
然后我尝试了此:
lst = list('12345')
def get_generator(lst):
yield from lst
gen_on_lst = get_generator(lst)
del lst
print(list(gen_on_lst))
输出是['1', '2', '3', '4', '5']
,我期望有错误。
那么当我使用del时会发生什么?我的猜测是,生成器生成了一个别名(可能是世界上无法访问的?),当我使用del
时,它仅删除内存中实际列表的一个别名,并且由于存在别名(在内存中,所以不释放内存)生成器)指向它。假设生成器将删除其内部别名,则在使用生成器时,内存将可释放,对吗?
或者,虽然不太可能,但是列表从内存中被丢弃只是时间问题,运气不好,在释放基础列表之前,我消耗了生成器。
您所说的别名在Python术语中称为“引用”。 Python中的每个对象都有一个引用计数*。 del
的作用是将该对象的引用计数减少一。
当对象的引用计数达到0时,可以对其进行垃圾回收。
这与Python中变量的性质有关。 “变量”不过是对象(或对对象的引用)的标签。
当你做的时候
a = 'foo'
字符串对象'foo'
的引用计数增加1。
有关更多信息,请参见Chapter 3的Python Language Reference。
((*请注意,我故意在此省略了一些细节。)