python 为什么每次代码运行时间不同-为什么你写的Python运行的那么慢呢?
大约在一年前,也就是2013年在Waza(地名),Alex Gaynor提到了一个很好的话题:为什么用Python、Ruby和Javascript写的程序总是运行的很慢呢?正如他强调的,关键就是现在出现了这个问题。换一句话说,尽管现在这种语言很慢,但不意味着没有解决办法,不意味着未来会一直这样。
当在网上问为什么Python比C语言更慢,回答最多的就是Python中有动态类型。然而,动态类型确实会在性能方面有影响,但是这并不是主要原因。
动态类型(像Python一样的主要编程语言都一样)使得编译器很难优化性能。动态使得每次执行都可能很不同,编译器难以优化。然而,正如Alex在谈话中提到的,我们花费了数年的时间来研究究竟在运行时进行类型检查的最好的办法是什么。但是没什么进展。
在现实中,在C语言和Python在运行时的巨大的不同是由于数据结构和算法的不同。有时程序员也没有注意到这一点。
用Python写不同的代码
让我们用一个Alex提到的实例来说明问题。一个Python程序员可能很喜欢用下面的例子表示一个平面上的点:
1
point= {'x':0,'y':0}
这种方法很易读,容易编码,形式很优雅。
另一个方面,一个C语言程序员可能使用结构体来表示平面上的点:
1
2
3
4
struct Point {
int x;
int y;
};
尽管这种方法也和Python能一样的工作并且都是很优雅的,但这是完全不同的数据结构。这里我们告诉了编译器,我们有两个字段x和y。知道了这两个字段的类型,编译器将分配一块连续的内存来储存这两个数据。换一句话说,就像一个数组一样。任何时间,编译器都知道给定的x和y在哪里。我们可以很容易地访问这些数据,就像是访问某些常数据一样。
Python使用哈希散列的方法来解决类似的问题。所以编译器不能简单地分配连续内存存储x和y来处理这些问题。由于我们在其中任意的地方都可能出现这些键。如果我们想的话,我们也可能删除这些键。编译器必须要使用哈希函数来映射到你可能让他指向的任何存储单元。不用说,这些函数增加了处理时间。尽管也许减缓的很小,但是足可以拖慢你的代码,尤其是这种情况如果很多的时候。
如果就是想将Python翻译成C语言的话,可能就像下面这样:
1
2
3
std::hash_set point;
point[“x”]= x
point[“y”]= y
看这个代码片段,好像就是语言的设计者他们自己故意尽力使哈希表复杂,因此尽管是正确的,但没有人使用。由于这个原因,写C语言的人可能认为这是不可思议的,但为什么在Python就是可以接受的呢?
原因就是写Python代码的人的“dictionaries are lightweight objects”这种心态。看下面的代码,这在Python中最接近C语言结构体:
1
2
3
4
class Point(object):
x, y= None,None
def __init__(self, x, y):
self.x,self.y= x, y
这对编译器是有用的,就像是C语言的结构体。例如第二行,我们明确告诉编译器但我们创造一个对象时我们总是至少需要两个数据段,我们希望编译器处理这个问题。
不幸的是这种标准的Python被叫做CPthon,不能总被使用。在我的机器上,下面的代码要执行186毫秒:
1
2
3
4
5
6
def sum_(points):
sum_x, sum_y= 0,0
for pointin points:
sum_x+= point['x']
sum_y+= point['y']
return sum_x, sum_y
在我的机器上,用point.x代替point['x']会花费201毫秒。也就是说,会慢了8%。
在CPthon中,point.x通常就是被处理成dict(point)['x']。这意味着带着点的class仍然像以前一样使用字典(dictionary)的方法查找。这样的话,就很容易看出为什么directionary的方法被看为“轻量级的”。
一些Python写的代码就是为了效率而设计的,例如PyPy,能很快地执行。如果不使用Python而是使用PyPy,同样的代码片段执行时间分别是21.6和3.75毫秒。这种方法相比CPython在JIT-capable编译情况下结果都是令人满意的。换一句话说,PyPy能正确地使用数据结构。
我希望你再一次看这个最短时间3.75毫秒。这个数字表明我们能在一秒进行266000次运算,这些事来自Python的,其中有动态绑定,monkey-patching(在不改变源代码的情况下扩展或修改动态语言运行时代码的方法)等。所有的这些,都是在编码和实现中使用了更好的数据结构。下一次当你在用Python写一行代码时,想一想你在使用什么数据结构,显示的还是隐式的,考虑一下是否有更好的办法。这就是你用C语言写程序时考虑的,不是吗?
最后,我愿意相信这个文章是表明为什么Python是一个有前途的语言的一个清楚的例子(或者是类似的语言)。这表明了标准的Python实现,这里的CPython仅仅是作为一个参考,它从来就不是被设计用来更快地执行的。正如我们今天可以看到的,像PyPy一样的算法实现是可以优化你的代码到一个很好的长度。随着语言的自然发展,这些优化是可能的。我们仅仅用Python编程过23年,那么如果像C语言一样有42年的发展,Python会是什么样子呢?
1、有人也许会争辩说collections.namedtuple()是更接近于C语言的结构体,这是对的,但我们不要过分将事情复杂化,我们的重点是有效。
2、为了更清楚python是怎样工作的,请参考python文档。
python 为什么每次代码运行时间不同-为什么你写的Python运行的那么慢呢?相关推荐
- python 为什么每次代码运行时间不同-python – 气流在同一个dag的不同时间运行任......
我在dag中有30个单独的任务,它们之间没有依赖关系.任务运行相同的代码.唯一的区别是数据量,有些任务将以秒为单位完成,有些任务需要2小时或更长时间. 问题是在追赶期间,以秒结束的任务被在完成下一个执 ...
- python中控制代码块逻辑关系_一、Python基础知识
1.1 Python简介 (1)解释型语言 解释型语言在运行程序的时候才逐行翻译.运行. ①优点: 有良好的平台兼容性,在任何环境中都可以运行(安装了解释器)灵活,修改代码的时候直接修改就可以,可以快 ...
- python实现推荐系统代码_推荐系统之矩阵分解及其Python代码实现
有如下R(5,4)的打分矩阵:("-"表示用户没有打分) 其中打分矩阵R(n,m)是n行和m列,n表示user个数,m行表示item个数 那么,如何根据目前的矩阵R(5,4)如何对 ...
- python优点是代码库支持、灵活_C++和Python混合编程的利器
Python是一种简单易学.功能强大的编程语言,它有高效率的高层数据结构,能简单而有效地实现面向对象编程.Python简洁的语法.对动态输入的支持和解释性语言的本质,使得它在很多领域的大多数平台上都是 ...
- python第一行代码_“少年py”001:下载Python软件,写第一行代码
Python,网络上称之为人工智能时代的第一编程语言. 功能超级强大,能做科学计算.大数据处理.网络爬虫.游戏开发等等. 但是说实话,彬哥玩Python还没到这么厉害的程度,究竟怎么实现,我们不着急, ...
- python人脸识别代码百度ai_强大的AI!Python几行代码,就能预测未来孩子的长相?...
这次,将百度智能云中的人脸识别功能与python结合起来进行实验花了一些时间.结果非常令人满意,而且过程非常简单而不复杂.或许,你可以整合你孩子的外貌.让我们一起敲击键盘. 准备百度人工智能开放平台账 ...
- python k线合成_手把手教你写一个Python版的K线合成函数
手把手教你写一个Python版的K线合成函数 在编写.使用策略时,经常会使用一些不常用的K线周期数据.然而交易所.数据源又没有提供这些周期的数据.只能通过使用已有周期的数据进行合成.合成算法已经有一个 ...
- python识别数字程序_python实现识别手写数字 python图像识别算法
写在前面 这一段的内容可以说是最难的一部分之一了,因为是识别图像,所以涉及到的算法会相比之前的来说比较困难,所以我尽量会讲得清楚一点. 而且因为在编写的过程中,把前面的一些逻辑也修改了一些,将其变得更 ...
- 怎么把python程序发给别人_想把你写的Python程序发给别人用?打包成exe啊!
前言 大家好,欢迎来到编程教室! 当你学了一段时间Python,终于写出一个小游戏的时候,是不是很想发给你的小伙伴分享一下你的成果?但是,如果直接将xx.py文件发给别人,别人通常是不能直接运行的,他 ...
最新文章
- iOS----------计算一段代码执行时间
- 【连载】高效人士的116个IT秘诀(第2版)——秘诀25快速记录你的工作日志
- Windows环境下配置环境变量
- 彻底解决 libhdf5_hl.so.10: cannot open shared object file: No such file or directory
- 第一节:数据库与数据仓库
- 厚积薄发,拥抱 .NET 2016
- stm32驱动LTC6912程控放大器程序,PGA可编程增益放大器,可调增益运放电路
- Office365—Exchange管理4—通讯组和安全组
- kubernetes kubelet参数
- python Word批量转PDF
- 批处理大全Win10版工具箱
- 解决TypeError: conv2d() received an invalid combination of arguments
- 《速度与激情》男主演保罗沃克车祸身亡,再见速度再见难续的激情
- 知道邻边和斜边求角度_知道一个角度和一条对边怎样求斜边和邻边
- 计算机启动如何改变默认硬盘,如何把硬盘设置为第一启动项怎么修改的
- 6.3.3 延迟缓存
- android编程root启动指定app,取之有道——巧用Root权限 启动其他APP中的Activity
- Jetson Nano - 自己动手搭建Jetbot环境
- Mockito之使用Answer
- 欢乐颂之鸿蒙系统,《欢乐颂3》开机惹众议,蒋欣王子文疑似被换?导演是这样回复的...
热门文章
- [原创]一起来做网页游戏---前言
- Mysql的row_format(fixed与dynamic)
- P3979 遥远的国度
- 【蓝桥杯】历届试题 地宫取宝
- angularjs(1)
- JavaScript快速入门(六)——DOM
- ZedBoard学习(5)-ZedBoard和System Generator
- WPF and Silverlight 学习笔记(十八):WPF样式(Style)与模板(Template)
- matlab 最小一乘法,MATLAB实现最小二乘法
- python怎么导入视频-python 给视频添加马赛克