为什么你写的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<span> point;

point[“x”] = x

point[“y”] = y</span>

  看这个代码片段,好像就是语言的设计者他们自己故意尽力使哈希表复杂,因此尽管是正确的,但没有人使用。由于这个原因,写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 point in 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文档。

  原文 lukauskas.co.uk

时间: 2024-08-12 20:54:37

为什么你写的Python运行的那么慢呢?的相关文章

luigi框架--关于python运行spark程序

首先,目标是写个python脚本,跑spark程序来统计hdfs中的一些数据.参考了别人的代码,故用了luigi框架. 至于luigi的原理 底层的一些东西Google就好.本文主要就是聚焦快速使用,知其然不知其所以然. python写Spark或mapreduce还有其他的方法,google上很多,这里用luigi只是刚好有参考的代码,而且理解起来还是简单,就用了. 上代码: import luigi, sysfrom datetime import datetime, timedeltafr

配置Sublime Text 2 的Python运行环境

Sublime Text 2作为一款轻量级的编辑器,特点鲜明,方便使用,愈发受到普罗大众的喜爱,我个人最近也开始用了起来.同时,我近段时间还在学习Python的相关东西,所以开始用ST2来写Python,所以把配置方法略微总结一下. 1. 在工具栏点击Preferences,打开Browse Packages.在打开的文件夹中找到Python,并打开这个文件夹.找到文件Python.sublime-build,并打开. 2. 修改以下内容: { "cmd": ["python

为什么python运行的慢

最近在leetcode刷题,明显的注意到同样的算法,python运行的要慢的多,查资料得到python运行的慢主要原因如下: 一.动态类型导致运行速度慢,在北邮人论坛里面的这篇帖子中有较为详细的解释,原文中有举例说明,本文没有例子讲解只是提取了原理来讲解,内容主要如下: (原文链接:http://bbs.byr.cn/#!article/Python/68) a.动态语言中的执行过程 Python等动态类型语言之所以慢,就是因为每一个简单的操作都需要大量的指令才能完成.他们的虚拟机拥有很强的优化

Python黑帽编程1.3 Python运行时与包管理工具

Python黑帽编程1.3  Python运行时与包管理工具 0.1  本系列教程说明 本系列教程,采用的大纲母本为<Understanding Network Hacks Attack and Defense with Python>一书,为了解决很多同学对英文书的恐惧,解决看书之后实战过程中遇到的问题而作.由于原书很多地方过于简略,笔者根据实际测试情况和最新的技术发展对内容做了大量的变更,当然最重要的是个人偏好.教程同时提供图文和视频教程两种方式,供不同喜好的同学选择. 0.2 前言 前两

Python运行的方式

Python的运行方式多种多样,下面列举几种: 交互式 在命令行中输入python,然后在>>>提示符后面输入Python语句,这里需要注意: 1 语句前面不能有空格,否则会报错 2 对于符合语句,前面会有...提示符,结束符合语句的方法是按下Enter键 命令行运行文件 以命令行运行文件有两种形式: 1 将文件保存为.py,然后在命令行用python 文件名.py的方式运行 2 将文件当成shell脚本,以运行shell的方式运行,此时在文件第一行,需要写#!/usr/bin/pyth

代写python,代写python编程,python代写,python编程代写,留学生python代写

代写python,python代写,代写python编程,python编程代写,留学生python代写 本人以及代写团队成员均毕业于国内.海外计算机专业知名学府,现均就职于国内顶尖互联网企业任职高级开发工程师,现利用闲暇之余接编程代写,具体接单范围如下: 代写python,python代写,python编程代写,python课程远程辅导 代写C语言,代写C++ 代写java,java编程代写 代写操作系统operation system 代写计算机网络computing network 代写Li

python运行时报错can&#39;t find &#39;__main__&#39; module in &#39;xxx&#39; 的解决办法

刚开始学习python,想要使用pycharm来编辑和运行程序,所以就安装了下pycharm ,写了个简单的代码决定运行下,结果出现如下错误: 度娘找了一番,解决了问题,发现错误主要因为在这里 没有运行的成功的原因就是这里没有选择*.py 文件. 选择目标文件夹当动中的 *.py 文件. python运行时报错can't find '__main__' module in 'xxx' 的解决办法 原文地址:https://www.cnblogs.com/dcx-1993/p/10306327.h

Python逆向(一)—— Python运行原理

一.什么是Python Python 是一种解释型.面向对象.动态数据类型的高级程序设计语言. 二.解释型语言和编译型语言的区别 我们编程都是用的高级语言,计算机不能直接理解高级语言,只能理解和运行机器语言,所以必须要把高级语言翻译成机器语言,计算机才能运行高级语言所编写的程序.翻译的方式有两种,一个是编译,一个是解释. 用编译型语言写的程序执行之前,需要一个专门的编译过程,通过编译系统(不仅仅只是通过编译器,编译器只是编译系统的一部分)把高级语言翻译成机器语言(具体翻译过程可以参看下图),把源

python运行提示缺少模块 No module named &#39;XX&#39;

背景: 在pycharm中运行正常,但是使用命令方式就提示没有模块 解决方案 在Python安装目录下的\Lib\site-packages文件夹中建立一个.pth文件,内容为自己写的 查看包是否有导入 再次运行,就成功了 python运行提示缺少模块 No module named 'XX' 原文地址:https://www.cnblogs.com/chongyou/p/12616691.html