为何未清空却在Python程序中得到空的mapped_list?求解释
为什么未清空mapped_list却得到了空列表?
这是个很典型的Python迭代器特性问题,我来给你拆解清楚:
首先先贴出你的代码方便对照:
numbers = {} # 为字典'numbers'赋值 for i in range(5): numbers[i**2] = i # 判断数字是否在numbers字典中的函数 def check(x): if x in numbers: return True else: return False # 随机数字列表 rand_nums = [8,9,25,16,18] filtered_list = filter(check,rand_nums) # 打印filtered_list # 注意:使用list()构造函数打印filter对象 print(list(filtered_list)) # 加1函数 def add(x): return x+1 mapped_list = map(add,filtered_list) # 打印mapped_list # 注意:使用list()构造函数打印map对象 print(list(mapped_list))
核心原因:迭代器是一次性消耗的
你这里的filtered_list是filter()函数返回的迭代器对象,Python里的迭代器有个关键特性:只能被遍历一次,遍历完成后就会被耗尽,不会再产生任何元素。
具体到你的代码流程:
- 当你第一次执行
list(filtered_list)时,Python会遍历这个filter迭代器,把所有符合条件的元素(也就是[9,25,16])取出来转成列表打印。这时候迭代器的内部指针已经走到了末尾,没有剩余元素了。 - 之后你用这个已经被耗尽的迭代器去创建
map对象mapped_list,当你再执行list(mapped_list)时,map会尝试遍历filtered_list,但这个迭代器已经空了,自然就得到了空列表。
解决办法
有两种常见的解决思路:
- 提前转成列表保存:把filter的结果先转成列表,这样后续可以重复遍历(列表是可迭代对象,不是一次性迭代器)。修改代码如下:
numbers = {} for i in range(5): numbers[i**2] = i def check(x): return x in numbers rand_nums = [8,9,25,16,18] # 提前转成列表,保存所有过滤结果 filtered_list = list(filter(check,rand_nums)) print(filtered_list) # 输出 [9,25,16] def add(x): return x+1 mapped_list = map(add,filtered_list) print(list(mapped_list)) # 输出 [10,26,17] - 重新创建迭代器:如果需要保留惰性求值的特性(比如处理超大数据集时节省内存),可以在需要使用的时候重新调用
filter()生成新的迭代器:numbers = {} for i in range(5): numbers[i**2] = i def check(x): return x in numbers rand_nums = [8,9,25,16,18] # 第一次创建迭代器并打印 print(list(filter(check,rand_nums))) # 输出 [9,25,16] def add(x): return x+1 # 重新创建一个新的filter迭代器给map用 mapped_list = map(add, filter(check,rand_nums)) print(list(mapped_list)) # 输出 [10,26,17]
内容的提问来源于stack exchange,提问作者lucifer
相关产品推荐
相关产品推荐

