我不确定我的标题是否适合我正在寻找的内容,但我认为引用是问题所在。
我有一个Reader对象,我可以通过它循环:
msrun = pymzml.run.Reader(mzmlFile)
for feature in msrun:
print feature['id']
使用此代码,我从msrun中获取所有功能的id,从1开始。但是,我需要首先遍历代码并获取我想要的所有密钥并将它们放在列表中,如下所示:
def getKeys(msrun, excludeList):
spectrumKeys = []
done = False
for spectrum in msrun:
if done:
break
if spectrum['ms level'] == 2:
for key in spectrum:
if key not in excludeList and not key.startswith('MS:'):
done = True
spectrumKeys.append(key)
spectrumKeys.extend(spectrum['precursors'][0].keys())
precursorKeys = spectrum['precursors'][0].keys()
break
return spectrumKeys, precursorKeys
但是,如果我要运行此代码:
msrun = pymzml.run.Reader(mzmlFile)
specKeys, precursKeys = getKeys(msrun, ['title','name'])
for feature in msrun:
print feature['id']
它从未在getKeys()循环中的id开始(它从11开始而不是1)。所以我猜pymzml.run.Reader()就像一个生成器对象。所以我试着复制这个对象。首先我试过
copyMsrun = msrun
specKeys, precursKeys = getKeys(copyMsrun, ['title','name'])
但是如果我理解正确的话会产生同样的问题,因为执行copyMsrun = msrun会使它们指向相同的东西。
然后我试了
import copy
copyMsrun = copy.copy(msrun)
但我仍然遇到同样的问题。我使用copy.copy而不是copy.deepcopy,因为我不认为Reader对象包含其他对象,当我尝试深度复制时,我得到了
TypeError: object.__new__(generator) is not safe, use generator.__new__().
那么如何做我复制一个对象,以便循环通过一个对象不会影响另一个对象?我应该做什么
msrun = pymzml.run.Reader(mzmlFile)
copyMsrun = pymzml.run.Reader(mzmlFile)
编辑: 关于Ade YU的评论,我也尝试过,但是当我做的时候
spectrumList = []
for spectrum in msrun:
print spectrum['id']
spectrumList.append(spectrum)
for spectrum in spectrumList:
print spectrum['id']
第一次打印给我1-10,但第二次打印给我十次10。
答案 0 :(得分:4)
从pymzML和文档的出版,很明显这种“病态设计”是故意的。初始化数千个频谱对象将产生巨大的计算开销,内存和CPU周期,这是根本不需要的。通常,解析大量的mzML会自然地要求分析时解析方法,而不是收集以后需要分析的所有内容。
话虽如此,pymzML仍然提供了简单地通过调用spectrum.deRef()来“深度复制”频谱的功能。使用此功能的优点是在复制之前将剥离所有不必要的数据,因此提供较小的对象。 pymzML deRef
run = pymzml.run.Reader(file_to_read, MS1_Precision = 5e-6, MSn_Precision = 20e-6)
for spec in run:
tmp = spec.deRef()
希望有所帮助。
答案 1 :(得分:2)
看起来你正在处理一个病态设计的课程。您正在使用的库中存在一些严重缺陷,尤其是迭代器反复生成相同对象的部分。
您可能需要复制迭代器的输出,如下所示:
objs = [copy.deepcopy(obj) for obj in pymzml.run.Reader(mzmlFile)]
for obj in objs:
# do something
for obj in objs:
# do something
如果这不起作用,你需要找到编写图书馆并没收他们电脑的人。
答案 2 :(得分:2)
尝试itertools.tee
,它为您提供独立的迭代器。如果这不起作用,你可能遇到麻烦,因为你的生成器产生的对象取决于某些外部状态,(id
=到目前为止产生的对象数量?),并且没有办法自动帮助在那种情况下。 deepcopy
是你最好的选择,但是如果这不起作用,你必须编写自己的类来捕获来自spectrum
对象的信息。
spectrumList = []
for spectrum in msrun:
spectrumList.append(MySpectrum(spectrum))
或较短的变体
spectrums = list(map(MySpectrum(msrun)))
你需要像
这样的东西class MySpectrum:
def __init__(self, spectrum):
self.id = spectrum.id
...
答案 3 :(得分:-1)
使用deepcopy模块分配它们而不指向同一个对象
from copy import deepcopy
myq=deepcopy(transq)