如何正确使用random.sample?按比例随机复制配对的图片与文本文件
解答你的两个问题
一、正确使用random.sample方法
random.sample是Python标准库里专门用来从可迭代对象(列表、集合等)中随机挑选指定数量不重复元素的工具,它不会修改原对象,而是返回一个全新的抽样列表,特别适合你需要选不重复文件对的场景。
核心用法
语法:random.sample(population, k)
population:要抽样的源序列/集合(必须非空)k:要抽取的元素数量,必须满足0 ≤ k ≤ len(population),否则会抛出ValueError
简单示例
比如从一组编号里随机选3个不重复的:
import random ids = ["im1", "news_im2", "pic3", "img4"] selected = random.sample(ids, 2) print(selected) # 每次运行结果不同,比如 ["news_im2", "img4"] 或 ["im1", "pic3"]
注意事项
- 如果源是集合,
random.sample会自动转为列表处理 - 不能用它处理无限迭代器,因为它需要先获取所有元素的长度
- 抽样的元素绝对不会重复,这刚好匹配你“选一组唯一文件对”的需求
二、按百分比随机复制同名图片和文本文件
结合你的需求,我写了一段带详细注释的代码,保证每次运行都能得到不同的随机结果:
完整代码实现
import os import shutil import random def copy_random_pairs(source_dir, target_dir, percent=0.4): # 1. 遍历源目录,找出所有.png图片,提取不带扩展名的文件名前缀 image_files = [f for f in os.listdir(source_dir) if f.lower().endswith('.png')] # 去重前缀(防止出现重名图片,根据你的描述这步可选,但加了更稳妥) file_prefixes = list({os.path.splitext(f)[0] for f in image_files}) if not file_prefixes: print("源目录里没找到任何.png图片") return # 2. 计算要抽取的文件对数量 sample_count = int(len(file_prefixes) * percent) # 避免百分比过低导致选0个的情况,可选调整 sample_count = max(sample_count, 1) # 3. 随机挑选前缀,每次结果不同(默认用系统时间做随机种子) selected_prefixes = random.sample(file_prefixes, sample_count) # 4. 创建目标目录(如果不存在) os.makedirs(target_dir, exist_ok=True) # 5. 复制对应的图片和文本文件 for prefix in selected_prefixes: img_src = os.path.join(source_dir, f"{prefix}.png") txt_src = os.path.join(source_dir, f"{prefix}.txt") # 复制图片 if os.path.exists(img_src): shutil.copy2(img_src, target_dir) print(f"已复制: {img_src}") else: print(f"警告:图片文件缺失: {img_src}") # 复制文本 if os.path.exists(txt_src): shutil.copy2(txt_src, target_dir) print(f"已复制: {txt_src}") else: print(f"警告:文本文件缺失: {txt_src}") # 调用示例,替换成你的实际路径 if __name__ == "__main__": source_folder = "./your_images_and_texts" target_folder = "./random_selected_pairs" copy_random_pairs(source_folder, target_folder, percent=0.4)
关键细节说明
- 每次结果不同:Python的
random模块默认会用系统当前时间作为随机种子,所以每次运行代码时,抽样结果都会不一样。如果你之前手动设置过random.seed(),记得删除那行代码,否则结果会固定。 - 百分比处理:代码用
int()取整,如果你需要更精确的向上取整(比如总共有101个文件,40%是40.4,要取41个),可以改用math.ceil(len(file_prefixes)*percent),记得先导入math模块。 - 容错处理:加了文件存在判断,避免个别文件缺失导致程序崩溃,你可以根据实际情况去掉或保留。
内容的提问来源于stack exchange,提问作者Jess
相关产品推荐
相关产品推荐

