有什么建议让这个脚本运行得更快?对于这个脚本,我通常有两到一千万行。
while True:
line=f.readline()
if not line:break
linker='CTGTAGGCACCATCAAT'
line_1=line[:-1]
for i in range(len(linker)):
if line_1[-i:]==linker[:i]:
new_line='>\n'+line_1[:-i]+'\n'
seq_1.append(new_line_1)
if seq_2.count(line)==0:
seq_2.append(line)
else:pass
else:pass
答案 0 :(得分:3)
首先,您似乎在内循环中创建了许多字符串对象。您可以先尝试构建前缀列表:
linker = 'CTGTAGGCACCATCAAT'
prefixes = []
for i in range(len(linker)):
prefixes.append(linker[:i])
此外,您可以使用string
的方法endswith
,而不是在内部循环中的条件中创建新对象:
while True:
line=f.readilne()
if not line:
break
for prefix in prefixes:
if line_1.endswith(prefix):
new_line='>\n%s\n' % line_1[:-len(prefix)]
seq_1.append(new_line_1)
if seq_2.count(line)==0:
seq_2.append(line)
我不确定那里的索引(如len(prefix)
)。也不知道它会有多快。
答案 1 :(得分:3)
我不确定你的代码是做什么的,但一般方法是:
但最重要的是:尝试简化和优化算法,而不一定是实现它的代码。
从代码判断并应用上述一些规则代码可能如下所示:
seq_2 = set() # seq_2 is a set now (maybe seq_1 should be also?)
linker = 'CTGTAGGCACCATCAAT' # assuming same linker for every line
linker_range = range(len(linker)) # result of the above assumption
for line in f:
line_1=line[:-1]
for i in linker_range:
if line_1[-i:] == linker[:i]:
# deleted new_line_1
seq_1.append('>\n' + line_1[:-i] + '\n') # do you need this line?
seq_2.add(line) # will ignore if already in set
答案 2 :(得分:2)
问题的很大一部分可能是seq_2.count(line) == 0
测试line
是否在seq_2
。这将遍历seq_2
的每个元素,并测试它是否等于line
- 随着seq_2
的增长,这将花费更长时间。您应该使用一个集合,它将为您提供恒定时间测试,以确定它是否通过散列存在。这将丢弃seq_2
的顺序 - 如果你需要保留订单,你可以使用一个集合和一个列表(测试它是否在集合中,如果没有,则添加到两者)。
这可能不会影响速度,但是使用for line in f
循环while True
而不是line = f.readline()
循环并测试何时中断更好。此外,else: pass
语句完全没有必要,可以删除。
linker
的定义应移到循环之外,因为它不会被更改。 @ uhz关于预建前缀和使用endswith
的建议也可能不错。
答案 3 :(得分:0)
比所有theese变种快两倍(至少在python 2.7.2)
seq_2 = set()
# Here I use generator. So I escape .append lookup and list resizing
def F(f):
# local memory
local_seq_2 = set()
# lookup escaping
local_seq_2_add = local_seq_2.add
# static variables
linker ='CTGTAGGCACCATCAAT'
linker_range = range(len(linker))
for line in f:
line_1=line[:-1]
for i in linker_range:
if line_1[-i:] == linker[:i]:
local_seq_2_add(line)
yield '>\n' + line_1[:-i] + '\n'
# push local memory to the global
global seq_2
seq_2 = local_seq_2
# here we consume all data
seq_1 = tuple(F(f))
是的,这是丑陋和非pythonic,但它是最快的工作方式。
您也可以在生成器内部使用with open('file.name') as f:
升级此代码,或者添加其他逻辑。
注意:
这个地方'>\n' + line_1[:-i] + '\n'
- 值得怀疑。在某些机器上,它是连接字符串的最快方法。在某些机器上,最快的方法是'>\n'%s'\n'%line_1[:-i]
或''.join(('>\n',line_1[:-i],'\n'))
(当然,在没有查找的版本中)。我不知道什么对你最好。
这很奇怪,但我的计算机上的新格式化程序'{}'.format(..)
显示最慢的结果。