Python中使用ProDy生成PDB文件时,列表最后一项覆盖所有文件内容的问题
Python中使用ProDy生成PDB文件时,列表最后一项覆盖所有文件内容的问题
嘿,我一眼就瞅出你代码里的问题啦——嵌套循环的逻辑完全错了,导致每个PDB文件被所有pocket的内容反复写入,最后一次写入的自然是最后一个pocket的内容,所以所有文件都被它覆盖了。
先给你上能直接解决问题的代码,两种写法任你选:
写法1:边处理边写入(更省内存)
不用先把所有内容存到列表里,处理一个PDB ID就直接生成对应的口袋文件,逻辑最清晰:
ids = ['1b7f', '3wbm'] for pdb_id in ids: # 解析PDB文件 p = parsePDB(pdb_id) # 筛选口袋区域 pocket = p.select('within 4.5 of protein and nucleic') # 生成对应文件名 filename = f"{pdb_id}_pocket.pdb" # 直接写入 writePDB(filename, pocket)
写法2:先收集再配对写入(适合需要复用pockets的场景)
如果确实需要先把所有pockets和文件名都存起来,那一定要用zip把两个列表一一对应,而不是嵌套遍历所有组合:
ids = ['1b7f', '3wbm'] pockets = [] names = [] # 先收集所有口袋和对应的文件名 for i in ids: p = parsePDB(i) pocket = p.select('within 4.5 of protein and nucleic') pockets.append(pocket) names.append(f"{i}_pocket.pdb") # 一对一配对写入,每个文件名对应唯一的pocket for name, pock in zip(names, pockets): writePDB(name, pock)
为啥你的原代码会出问题?
你原来的代码里,在生成names的循环中又嵌套了两层循环:
for n in ids: name = n + '_pocket.pdb' names.append(name) for a in names: for pock in pockets: writePDB(a, pock)
这会导致:
- 每新增一个文件名,就会把所有已存在的文件名,用所有的pocket各写一遍
- 比如生成第二个文件名
3wbm_pocket.pdb时,会先把1b7f_pocket.pdb用第一个pocket写一遍,再用第二个pocket写一遍(直接覆盖),接着对3wbm_pocket.pdb做同样操作,最后所有文件自然都是最后一个pocket的内容
至于你想尝试的map函数,其实也能实现,但需要用lambda包装参数,比如:
from functools import partial # 先把每个文件名和对应的pocket绑定 for name in names: # 固定文件名,生成只接受pocket的函数 bound_write = partial(writePDB, name) # 不过这里还是要注意一一对应,不能直接遍历所有pockets # 所以其实还是zip配对更直观
但说实话,这种写法可读性不如直接用zip循环,没必要舍近求远~




