为啥我的Python这么慢 (一)
在Python系列教程中,我们提到一个概念字符串是不可修改的。这一点可以通过id
函数来判断确实是对的。但是这个概念会对我们写作程序有什么影响一直没有特别深的理解。
直到有一次,实验室一个朋友要读基因组数据,结果发现3 G
的基因组读一晚上都没读完,就很诧异,看了下代码,这么写的。
基因组序列是GRCh38.fa
,FASTA
格式,序列行每行70
个字符,共44,284,892行 (记住行数有多大),示例如下。
>chr1
NNNNN...(60个N)...NNNNN
ACGTA...(60个Nt)...ACGTA
...
>chr2
NNNNN...(60个N)...NNNNN
ACGTA...(60个Nt)...ACGTA
...
读取程序如下(这里只选了读取基因组的部分,点击查看更多FASTA的操作):
aDict = {}
for line in open("GRCh38.fa"):
if line[0] == '>':
key = line[1:-1]
aDict[key] = ''
else:
aDict[key]+=line.strip()
程序看上去没问题,获取id
,读取一行"追加"在前一行后面,逻辑是对的。然后运行上程序,回去睡觉,满心欢喜期待第二天早上获得结果,结果啥也没出来,程序还停留在读取基因组序列步骤。
按我们服务器的性能,这不应该啊。看代码是不是出问题了,怎么看逻辑都对。后来就想会不会是序列累加的问题,换了一个写法。代码稍微长了些,先存入列表,再连接起来。
Dict = {}
for line in open("GRCh38.fa"):
if line[0] == '>':
key = line[1:-1]
aDict[key] = []
else:
aDict[key].append(line.strip())
#--------------------------------
for key, value in aDict.items():
aDict[key] = ''.join(value)
使用time
函数,查看下运行速度,不足1分钟。time
及更多程序监测方法见命令运行监测和软件安装。
time readFaJoin.py
real 0m51.256s
user 0m40.729s
sys 0m10.425s
不比不知道,一比吓一跳;速度差了何止几千倍。
这时,我们重新理解下什么叫字符串不可修改。
使用id
函数来确定字符串累加跟列表累加的不同。(不同电脑或不同时间运行获得的id
不同,不看具体数字,只看id
的变化)
ehbio = "Sheng Xin Bao Dian"
id(ehbio)
## Output: 140405359946640
ehbio += ' very good'
ehbio
## Output: 'Sheng Xin Bao Dian very good'
id(ehbio)
## Output: 140405344262576
同样的变量名字,但不同的id
。就是说python在对变量ehbio
新增字符串时,是先开辟一份内存空间,把ehbio
原有内容加新内容组成的字符串存入新的内存空间。而不是想象中的直接追加在已有字符串的后面。这样对4千万行数据的操作就是要做4千万次的内存空间开辟和字符串存储。这是一个特别耗时的步骤。
而如果是一个列表呢?
aList = ['Sheng','Xin']
id(aList)
## Output: 140405344245520
aList.append("Bao")
id(aList)
## Output: 140405344245520
aList.extend(["Dian", "excellent"])
id(aList)
## Output: 140405344245520
而列表就不一样了,无论是使用append
增加一个元素,还是使用extend
增加一组元素,列表变量aList
的id
都没有变化。说明这是追加,不是新建。
Python
使用中还有不少类似这样的需要注意的小细节,在后续会陆续推出。
- 跨域资源共享(CORS)在ASP.NET Web API中是如何实现的?
- 使用腾讯云 GPU 学习深度学习系列之六:物体的识别与定位
- npm5 新版功能特性解析及与 yarn 评测对比
- H5直播避坑指南
- 龙门阵之 DevOps 门外汉须知
- 全面进阶 H5 直播(上)
- 这年头,不会斗图都毕不了业?
- 龙妈也会死?《权力的游戏》 AI 算法预测丹妮女王危在旦夕
- 腾讯云 GAME-TECH 沙龙干货回顾:海外网络拓展及质量把控
- 通过扩展让ASP.NET Web API支持W3C的CORS规范
- 腾讯云GAME-TECH沙龙干货回顾:腾讯游戏云全球化实践
- 腾讯云GAME-TECH沙龙干货回顾:猎豹游戏出海经验分享
- 腾讯云GAME-TECH沙龙干货回顾:绿洲全球化案例分享
- 基于云计算的 CV 移动交互应用研究(1):CV交互+云计算
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 树状数组-HDU3015 Disharmony Trees
- 放弃fastjson,拥抱Jackson
- Spring入门
- 贪心-HDU1789 Doing Homework again(活动安排问题)
- flink实战-实时计算平台通过api停止流任务
- JAVA初级岗面试知识点——基础篇
- flink实战-flink streaming sql 初体验
- flink实战教程-使用set实时计算当天网站uv
- 贪心-HDU3348 coins(钱币问题)
- 归并排序详解 -HDU4911 Inversion(逆序对)
- 数据结构与算法——稀疏数组
- Maven安装配置详细教程
- 数据结构与算法——冒泡排序
- MyBatis Generator逆向工程-你还在手写mapper吗?
- JSR303后端校验详解