列表推导式含else分支print时失效问题求助
列表推导式添加print后过滤失效的原因及解决方法
问题重现
原始循环代码:
for f in src_files.copy(): # Iterate over a list of images if os.path.getsize(os.path.join(SOURCE_DIR, f)) == 0: # Check if filesize is 0 print("filename is zero length, so removing.") src_files.remove(f) # Remove corrupted files from list
不含print的列表推导式可正常过滤:
src_files = [f for f in src_files if os.path.getsize(os.path.join(SOURCE_DIR, f)) > 0]
但添加else分支的print后,过滤逻辑失效,列表未正确过滤:
src_files = [f if os.path.getsize(os.path.join(SOURCE_DIR, f)) > 0 else print("filename is zero length, so removing.") for f in src_files]
失效原因
你写的是带三元表达式的列表推导式,而非带过滤条件的列表推导式:
- 带过滤条件的列表推导式格式是
[元素 for 元素 in 可迭代对象 if 条件],这种写法会直接跳过不满足条件的元素,只保留符合要求的内容。 - 而你用的
[元素 if 条件 else 替代值 for 元素 in 可迭代对象],会为每一个输入元素生成一个输出元素:条件满足时生成f,不满足时生成print(...)的返回值(print()函数的返回值是None)。最终你的列表里会混合有效文件路径和大量None,等于没有过滤掉无效元素,只是把它们替换成了None。
解决方案
针对海量图片场景,需要兼顾效率(避免重复文件IO)和需求(打印无效文件提示),推荐以下几种方式:
方式1:一次遍历完成打印与过滤(高效无重复IO)
这种方式只调用一次os.path.getsize,避免重复读取文件属性,适合处理大体积文件:
valid_files = [] for f in src_files: file_path = os.path.join(SOURCE_DIR, f) file_size = os.path.getsize(file_path) if file_size == 0: print(f"filename {f} is zero length, so removing.") else: valid_files.append(f) src_files = valid_files
方式2:先收集无效文件打印,再过滤(简洁但有重复IO)
如果追求代码简洁,可先遍历打印无效文件,再用列表推导式过滤,但会调用两次os.path.getsize:
# 先打印所有无效文件 for f in src_files: if os.path.getsize(os.path.join(SOURCE_DIR, f)) == 0: print(f"filename {f} is zero length, so removing.") # 再过滤有效文件 src_files = [f for f in src_files if os.path.getsize(os.path.join(SOURCE_DIR, f)) > 0]
方式3:用海象运算符(Python 3.8+)实现单列表推导+打印
利用Python 3.8引入的海象运算符:=,在列表推导的条件中完成size计算和打印,既简洁又避免重复IO:
src_files = [ f for f in src_files if (size := os.path.getsize(os.path.join(SOURCE_DIR, f))) > 0 or (print(f"filename {f} is zero length, so removing."), False)[1] ]
这里利用or的短路特性:当size>0时直接保留元素;当size=0时,执行print语句,然后返回False跳过该元素。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

