作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
查理(BCS, 普林斯顿大学)一直是可汗学院的工程领导, 然后雪松, 现在在Spring Discovery做ML.
Python 是惊人的.
令人惊讶的是,这是一个相当模糊的说法. 我说的“Python”是什么意思?? 我指的是抽象的Python吗 接口? 我指的是CPython,普通的Python吗 实现 (不要与同名的Cython混淆)? 或者我说的完全是别的意思? 也许我间接地指的是Jython、IronPython或PyPy. 或者也许我真的走得太远了,我在谈论RPython或rubpython(它们非常, 非常不同的东西).
而上面提到的技术是通用命名和通用引用的, 其中一些服务于完全不同的目的, 至少, 以完全不同的方式操作).
在我使用Python接口的整个过程中,我遇到了大量这样的接口 .* ython工具. 但直到最近,我才花时间去了解它们是什么, 它们是如何工作的, 为什么他们是必要的(以他们自己的方式).
在本教程中, 我将从头开始介绍各种Python实现, 最后是对PyPy的全面介绍, 我相信这是语言的未来.
这一切都始于对“Python”到底是什么的理解.
如果您对机器代码、虚拟机等有很好的理解,可以随意地 跳过.
这是的公点 Python初学者的困惑.
在进行比较时,首先要意识到的是“Python”是一个 接口. 有一个 规范 Python的什么 should 怎么做? should 行为(与任何接口一样). 有很多 实现 (与任何接口一样).
第二件要意识到的事情是“解释”和“编译”是an的属性 实现,不是。 接口.
所以这个问题本身并不是很好.
也就是说, 对于最常见的Python实现(CPython:用C编写), 通常简称为“Python”, 当然,如果你不知道我在说什么,你在用什么), 答案是: 解释, with some 编译. CPython 编译* Python源代码到字节码,然后 解释 这个字节码,在它运行时执行它.
* 注意:这不是传统意义上的“编译”. 通常, 我们会说“编译”就是把一种高级语言转换成机器代码. 但它是某种“汇编”.
让我们更仔细地看看这个答案, 因为它将帮助我们理解后面的一些概念.
理解字节码和字节码之间的区别非常重要. 机器代码(又名本机代码),也许最好的例子说明:
简单地说: 机器码要快得多,但字节码更易于移植和安全.
机器代码根据您的机器看起来不同,但字节码在所有机器上看起来都是一样的. 有人可能会说机器代码是 优化 到你的设置.
回到CPython实现,工具链流程如下:
正如我前面提到的,Python有 several 实现. Again, 如前所述, 最常见的是CPython, 但是为了这个比较指南,还有其他一些应该提到. 这是一个用C编写的Python实现,被认为是“默认”实现.
但是其他的Python实现呢? 其中一个比较突出的是 Jython一种利用JVM编写Java的Python实现. 当CPython生成在CPython VM上运行的字节码时,Jython生成 Java字节码 在JVM上运行(这与编译Java程序时生成的东西是一样的).
“为什么要使用替代实现呢?你可能会问. 首先,这些 不同的Python实现可以很好地使用不同的技术栈.
CPython使为Python代码编写C扩展变得非常容易,因为最终它由C解释器执行. 另一方面,Jython使与其他Java程序一起工作变得非常容易:您可以导入 any Java类,不需要额外的工作, 从Jython程序中调用并使用Java类. (旁白:如果你没有仔细考虑过,这实际上是疯狂的. 我们正处于这样一个阶段,你可以混合和混合不同的语言,并将它们编译成相同的内容. (正如 Rostin在美国,混合了Fortran和C代码的程序已经出现一段时间了. 所以,当然,这并不一定是新的. 但它仍然很酷.))
作为示例,这是有效的Jython代码:
[Java HotSpot(TM) 64位服务器VM (Apple Inc .).)].6.0_51
>>> from java.导入HashSet
>>> s = HashSet(5)
>>> s.add (" Foo ")
>>> s.add(“酒吧”)
>>> s
(Foo, Bar)
IronPython 是另一个流行的Python实现,完全用c#编写,目标是 .网络堆栈. 特别地,它运行在 .. NET虚拟机,微软的 公共语言运行时(CLR),与JVM相当.
你可能会这么说 Jython: Java: IronPython: c#. 它们运行在相同的虚拟机上, 你可以从IronPython代码中导入c#类,从Jython代码中导入Java类, etc.
完全有可能在不接触非cpython Python实现的情况下存活下来. 但是转换也有好处, 其中大部分依赖于你的技术栈. 使用大量基于jvm的语言? Jython可能适合您. 关于 .网络堆栈? 也许你应该尝试一下IronPython(也许你已经尝试过了).
顺便说一下,虽然这不是 reason 使用不同的实现, 请注意,这些实现在处理Python源代码的方式之外,实际上在行为上有所不同. However, 这些差异通常很小, 并且随着时间的推移,随着这些实现处于积极的开发中而消失或出现. 例如,IronPython 默认情况下使用Unicode字符串; CPython, however, 默认为ASCII 对于版本2.x(对于非ascii字符会出现UnicodeEncodeError错误),但不支持 默认为3的Unicode字符串.x.
所以我们有一个用C编写的Python实现,一个用Java编写,一个用c#编写. 下一个合乎逻辑的步骤:用…… Python. (受过教育的读者会注意到这有点误导.)
这就是事情可能变得混乱的地方. 首先,让我们讨论一下即时(JIT)编译.
回想一下,本机机器码比字节码快得多. 如果我们可以编译一些字节码然后作为本机代码运行呢? 我们必须付出一些代价来编译字节码(例如.e.但如果最终结果更快,那就太好了! 这就是JIT编译的动机, 一种混合了解释器和编译器优点的技术. 简而言之,JIT希望利用编译来加快解释系统的速度.
例如,jit采用的一种常见方法是:
这就是PyPy实现的全部内容:将JIT引入Python(参见 附录 感谢之前的努力). 有, 当然, 其他目标:PyPy的目标是跨平台, memory-light, 和stackless-supportive. 但JIT才是它真正的卖点. 作为一堆时间测试的平均值,据说它将性能提高了一个因子 6.27. 有关详细信息,请参见 PyPy速度中心:
PyPy有巨大的潜力,在这一点上 高度兼容的 使用CPython(所以 它可以运行Flask, Django, etc.).
但是围绕PyPy有很多困惑(例如,请参阅创建一个 PyPyPy…). 在我看来,这主要是因为PyPy实际上是两件事:
Python解释器 RPython (不是Python(我之前撒了谎)). RPython是Python的一个具有静态类型的子集. 在Python中,它是 “几乎不可能” 对类型进行严格的推理(为什么这么难? 我们考虑一下这个事实:
X =随机的.选择([1," foo "])
将是有效的Python代码(归功于 Ademan). 是什么类型的 x
? 当变量的类型没有被严格强制时,我们怎么能对变量的类型进行推理呢?). 与RPython, 你牺牲了一些灵活性, 而是让它变得更多, 更容易理解内存管理之类的东西, 哪一个允许优化.
一个编译器,为各种目标编译RPython代码并添加JIT. 默认平台是C, i.e.这是一个RPython-to-C编译器,但您也可以针对JVM和其他编译器.
仅为了清晰起见,在本Python比较指南中,我将它们称为PyPy(1)和PyPy(2)。.
为什么你需要这两样东西,为什么在同一屋檐下? 这样想:PyPy(1)是一个用RPython编写的解释器. 所以它接收用户的Python代码并将其编译成字节码. 但是解释器本身(用RPython编写)必须由另一个Python实现解释才能运行, right?
我们可以 使用CPython的 运行解释器. 但这不会很快.
而不是, 我们的想法是使用PyPy(2)(称为RPython工具链)将PyPy的解释器编译成另一个平台的代码.g.(C、JVM或CLI)在我们的机器上运行,也添加了JIT. 这很神奇:PyPy动态地将JIT添加到解释器中,生成自己的编译器! (再一次,这是疯狂的:我们正在编译一个解释器,添加另一个独立的编译器.)
最后, 结果是一个独立的可执行文件,它解释Python源代码并利用JIT优化. 这正是我们想要的! 这有点拗口,但也许这个图表会有所帮助:
再次重申, PyPy的真正美妙之处在于,我们可以在RPython中编写一堆不同的Python解释器,而不用担心JIT. 然后,PyPy将为我们实现JIT 使用RPython工具链/PyPy (2).
事实上,如果我们再抽象一点,理论上你可以为 any 语言,将其提供给PyPy,并获得该语言的JIT. 这是因为PyPy专注于优化实际的解释器, 而不是它所解释的语言的细节.
作为一个简短的题外话,我想提一下JIT本身是绝对迷人的. 它使用一种称为跟踪的技术,该技术执行 如下:
更多信息, 这篇论文 是非常容易理解和有趣的吗.
总结一下:我们使用PyPy的RPython-to-C(或其他目标平台)编译器来编译PyPy的rpython实现的解释器.
在对Python实现进行了长时间的比较之后,我不得不问自己:为什么这这么好? 为什么这个疯狂的想法值得追求呢? I think 亚历克斯·盖纳 把它放在他的身上 blog“(PyPy是未来),因为(它)提供了更快的速度, 更大的灵活性, 并且是Python发展的更好平台.”
简而言之:
Python 3000 (Py3k): Python 3的另一种命名.主修,主修; 向后不兼容的 Python的发行版 2008. Py3k团队预测,这需要大约 五年 这个新版本要被完全采用. 虽然 most (警告:坊间传言)Python开发人员继续使用Python 2.x,人们越来越意识到Py3k.
Numba:一个“即时专门化编译器”,将JIT添加到 带注释的 Python代码. 用最基本的术语来说,您给它一些提示,它就会加快部分代码的速度. Numba是…的一部分 水蟒 分发,一组用于数据分析和管理的软件包.
IPython与其他讨论的内容非常不同. Python的计算环境. 交互式,支持GUI工具包和浏览器体验等.
RubyPython: Ruby和Python虚拟机之间的桥梁. 允许您将Python代码嵌入到Ruby代码中. 您定义Python的启动和停止位置,然后rubypypython在vm之间封送数据.
PyObjc: Python和Objective-C之间的语言绑定,作为它们之间的桥梁. 几乎, 这意味着你可以从Python代码中利用Objective-C库(包括创建OS X应用程序所需的一切), 和Python模块从你的Objective-C代码. 在这种情况下,用C编写CPython很方便,C是Objective-C的子集.
PyQtPyObjc给你绑定OS X GUI组件, PyQt为Qt应用程序框架做同样的事情, 让您创建丰富的图形界面, 访问SQL数据库, etc. 另一个旨在将Python的简单性带给其他人的工具 框架.
世界级的文章,每周发一次.
世界级的文章,每周发一次.