Python 如何在不引用对象的情况下复制对象?
我不确定我的标题是否正确,但我认为引用是问题所在 我有一个读卡器对象,通过它我可以循环:Python 如何在不引用对象的情况下复制对象?,python,object,copy,Python,Object,Copy,我不确定我的标题是否正确,但我认为引用是问题所在 我有一个读卡器对象,通过它我可以循环: msrun = pymzml.run.Reader(mzmlFile) for feature in msrun: print feature['id'] 通过这段代码,我得到了msrun中所有特性的id,从1开始。但是,我需要首先循环代码,获取我想要的所有密钥并将它们放入列表中,如下所示: def getKeys(msrun, excludeList): spectrumKeys = [
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
objs = [copy.deepcopy(obj) for obj in pymzml.run.Reader(mzmlFile)]
for obj in objs:
# do something
for obj in objs:
# do something
但是,如果我要运行以下代码:
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对象不包含其他对象,当我尝试deepcopy时,我得到了
TypeError: object.__new__(generator) is not safe, use generator.__new__().
那么,我如何复制一个对象,使循环通过一个对象不会影响另一个对象呢?我该怎么办
msrun = pymzml.run.Reader(mzmlFile)
copyMsrun = pymzml.run.Reader(mzmlFile)
?
编辑: 在艾德·余的评论中,我也尝试过,但当我这么做的时候
spectrumList = []
for spectrum in msrun:
print spectrum['id']
spectrumList.append(spectrum)
for spectrum in spectrumList:
print spectrum['id']
第一次打印的结果是1-10,但第二次打印的结果是10乘以10。使用模块分配它们,而不指向同一对象
from copy import deepcopy
myq=deepcopy(transq)
看起来你正在处理一个病态设计的课程。您正在使用的库中存在一些严重缺陷,尤其是迭代器反复生成相同对象的部分 您可能需要复制迭代器的输出,如下所示:
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
objs = [copy.deepcopy(obj) for obj in pymzml.run.Reader(mzmlFile)]
for obj in objs:
# do something
for obj in objs:
# do something
如果这不起作用,您需要找到编写该库的人并没收他们的计算机。试试
itertools.tee
,它为您提供独立的迭代器。如果这不起作用,您可能会遇到麻烦,因为生成器生成的对象依赖于某些外部状态(id
=到目前为止生成的对象数?),在这种情况下无法自动提供帮助deepcopy
是您的最佳选择,但如果这不起作用,您必须编写自己的类来捕获光谱
对象中的所有信息
spectrumList = []
for spectrum in msrun:
spectrumList.append(MySpectrum(spectrum))
还是较短的变体
spectrums = list(map(MySpectrum(msrun)))
你需要像这样的东西
class MySpectrum:
def __init__(self, spectrum):
self.id = spectrum.id
...
从pymzML的出版和文档中可以清楚地看出,这种“病理学设计”是故意的。初始化数千个spectrum对象将产生巨大的计算开销、内存和cpu周期,而这些根本不需要。通常,解析大型mzML集自然需要在解析方法时进行分析,而不是收集稍后需要分析的所有内容 尽管如此,pymzML仍然提供了通过调用spectrum.deRef()来“深度复制”频谱的功能。使用此功能的优点是,在复制之前,所有不必要的数据都将被剥离,从而提供更小的对象
希望这会有所帮助。您可以在第一个循环中选择所需的信息,并将其存储在一些基本数据结构中,您可以轻松地进行操作。正如我在文章中所述,我的对象中没有对象,deepcopy会出错。这确实有效,但比msrun=pymzml.run.Reader(mzmlFile)慢得多copyMsrun=pymzml.run.Reader(mzmlFile)for copyMsrun中的obj:#在msrun中为obj做点什么:#做点什么,所以我正在使用它。谢谢你的答案,为了简单起见,我将按照我对迪特里希答案的评论方式来做。