“一百万行Python代码对任何人都足够了”
作者 | Jake Edge
译者 | Kolen
出品 | AI科技大本营(ID: rgznai100)
编程语言通常对其操作过程的各个方面都有或明或暗的限制。诸如标识符的最大长度或变量可以存储的值的范围之类的事情,这些是相当明显的例子,但是还有其他一些例子,其中许多是语言设计者未指明的,并且出现在各种实际应用语言编程的过程中。
这种模棱两可的限制可能会带来严重后果,因此在Python中确定各种各样的限制是“Python-dev”邮件列表(译者注:“Python-dev”是Python开发者社区的一个子栏目)上正在持续进行的讨论目标。
Mark Shannon发表了一项“对Python程序的各个方面(比如每个模块的代码行)实行一百万行限制”的提案。一百万看起来像是一个任意的数字(事实上也是如此),但他提出这一想法还是考虑到这个数字比较容易让人记住,因此可以使得程序员在对编程语言添加的限制而感到疑惑时无需查阅参考。
尽管有如此提案的想法,Python虚拟机存储的某些值(例如行号)是32位值,这显然固化了自身的限制,但是这样的值可能会浪费绝大多数一直没有关闭的Python程序的存储空间。除此之外,溢出这些32位值可能会导致安全性和其他类型问题的出现。
正如Shannon指出的,21位可以容纳的范围是从-1,000,000到1,000,000,其中三个值可以打包成一个64位字。“内存访问通常是现代CPU性能的一个限制因素。在ALU使用量适度增加(用于移位和屏蔽)的情况下,更好地打包数据结构可以增强局部性并减少内存[带宽]。” 他还指出,基于堆栈框架对象,代码对象和对象本身的数据结构可以通过这种打包的形式而受益。“还有一种潜在的更有效的指令格式,可以加快解释器的分派速度。”
他提议将限制用于以下Python程序的七个不同方面:
模块中的源代码行数
代码对象中字节码指令的数量
代码对象的局部变量和堆栈使用量的总和
代码对象中不同名称的数量
代码对象中的常量数
正在运行的解释器中的类别数
正在运行的解释器中的实时协同程序数
他还解决了“这不又是类似于‘640K对任何人来说应该已经足够了’?”的问题,这是一个当提出任意限制时,人们会立即想到的问题。他指出,Java虚拟机(JVM)将许多程序元素限制为65535(适合16位);这可能会产生限制,但主要是针对程序生成器,而不是手工编写的代码。他对Python提出的限制远不止于此,他认为这不会成为人为生成代码的真正障碍。他说到,“虽然生成的代码可能会超出限制,但代码生成器很容易修改其输出以符合标准。”
社区成员的一些回应
他为一些限制提供了简短的理由,但许多在这篇文章中发表过评论的人关心的是这些限制究竟能提供多少好处。Chris Angelico问Shannon是否做过任何评估,来看看会有多大的影响。Steven D'Aprano同意获得内存和安全性好处的前提,但他期望Python开发人员对预期的速度提高抱有“一点期望”。Steve Dower认为,总体的思路并非不合理,尽管他也有一些担忧:
“出于许多原因,选择小于2**32的任意限制肯定更安全,而且不太可能影响实际使用。我们已经有了一些低于10**6的实际限制(例如if/else深度和递归限制)。”
“也就是说,我真的不想影响边缘情况的使用,而且我非常熟悉其他任意限制的例子(任何文件系统都不需要超过260个字符的路径,对吧?:o))。”
Dower引用Windows MAX PATH值,该值将Win32 API中的路径名限制为最多260个字符。他认为,虽然每个模块的行数限制“感觉是最随意的”,但提出的几个限制似乎确实合理。注释和空行肯定会超过限制,这让他停顿思考了一下。他说,“‘正在运行的解释器中的类’”的有关限制有点令人担忧,但可能有办法处理超出此限制的程序,同时仍能获得它带来的所有收益:“即使没有其他的PEP,这里的好处似乎还是值得的。”
但Rhodri James认为,像这样提出的限制最终将成为某一部分人的问题;他也反对将计数打包成更小的比特宽度的想法,因为每次访问的掩蔽和移位效率均较低。Gregory P. Smith通常赞成限制,但他担心代码生成会与限制发生冲突;他指出,JVM限制在Android领域是一个大问题。线程中的其他人也指出JVM限制是有问题的。
Guido van Rossum对这个想法发表了一些的看法。他对所要解决的问题有些疑惑,并表示怀疑,例如,以20位而不是32位表示行号确实会大大提高效率。他担心“给生成代码带来麻烦的现有的(或偶然出现的)限制”。但他还指出,现有的CPython解析器只限于100个嵌套括号级别(以及可能还有嵌套的缩进级别),而且他没有听到过任何相关的吐槽。
Oscar Benjamin提到了一个具有一百万行的文件的真实案例。这是一个SymPy的测试文件,该文件使Python 3.6解释器崩溃了(尽管在3.7.1中已修复)。实际的测试大约只有3000行,但是pytest框架将其重写为一个包含一百万行的文件。本杰明还指出,一百万个字节码指令的限制更加严格。
Jim J. Jewett说,应该在语言本身的限制和CPython实现的限制之间进行区分。他指出“记录CPython选择实施的限制(特别是当前的选择),有很大的价值。” 但是,对语言本身来说,将限制设置得太高可能会遗漏MicroPython之类的实现。
“更改CPython(或至少在默认模式下为CPython)所支持的限制或其字节码格式可能很有价值,但应将其清楚地表述为CPython实现PEP(或字节码PEP),而不是一个语言更改PEP。”
PEP 611
Shannon接受了反馈,并将其反映在PEP611(“百万限制”)中。这就引出了另一个话题,在这个话题中,人们呼吁对变化进行某种基准测试,以便合理地评估变化。Barry Warsaw还说“对于你是建议使用Python作为语言限制,还是建议使用CPython作为实现限制,还缺乏明确性”。如果限制是针对语言的,“那么PEP需要声明,并且应该请求其他实现开发人员的反馈”。
几天后,Shannon要求评论人士更准确地表达他们的关心的问题。任一选择都有相关的成本,但仅简单地说明对更高限额的偏好并不完全有帮助:
“仅仅说你想要更大的限制是没有意义的。如果不需要为任意大的限制付出任何代价,那么我就不会首先提出PEP。”
“更高限额的成本由所有人承担,但收益却很少,请注意这一点。”
Angelico再次要求提供具体数字,但是Shannon说,性能的提高很难量化:“ 鉴于将启用的潜在优化数量无限,因此在数字上加一个数字有点困难:) ”。不出所料,这种回答并不完全受欢迎。但是部分问题可能是Shannon将潜在的优化部分地看作是限制所带来的其他优势的副产品。正如Nathaniel Smith所说:
“Mark,可能你想重新构造PEP,使其更像是‘这对正确性有好处,并且可以为解释器提供可靠的推理,这有很多好处(并且速度最终可能是其中之一)’我的印象是,你将加速视为次要动机,而其他人则感觉到加速是整个动机,因此,一种或多种方式会使人们感到困惑。”
Shannon说,做出这种改变当然需要理由,但他认为,目前的限制(或缺乏限制)是由于“历史事故和/或实施细节”造成的,这理由似乎很空洞。Van Rossum对这一说法持异议:
“哇哦,在现状中没有局限性(除了通过可用的内存间接地限制各种事物之外)最有可能是有意决策的结果。‘没有任意限制’是Python最初设计理念的一部分。我们并非总是成功(想到树的深度和调用递归深度),但这绝对是哲学。”
“你非常需要证明为什么我们现在应该改变。“无数的潜在优化”并没有消除它。“
Shannon回答说,这可能是语言哲学的一部分,“但实际上Python有很多限制。”例如,他指出,在一个代码对象中有231条以上的指令将导致CPython崩溃;这是一个可以修复的错误,但这类问题可能很难测试和查找。
“显式的限制更容易测试。超出限制的代码是否会以预期的方式失败并且恰好在限制以下的代码可以正常工作?”
“我想要的是允许更有效地使用资源,而又不会出现较低或未指定的限制。有限的机器上总会有一些限制。如果未指定它们,它们仍然存在,我们只是不知道它们是什么或它们如何表现出来。”
Van Rossum特别提出了对类数和协同程序数的限制,因为这是有问题的。更改对象标头(这是对类的限制所允许的一件事)是对C API的更改,因此他认为应该单独讨论。协同程序“只是另一个Python对象,没有与之相关联的操作资源”,因此他不明白为什么要专门针对它们。其他人同意协同工作,并提出了可能需要超过一百万个应用程序的建议。这些反对意见导致Shannon放弃了PEP中的协同程序,因为“限制协同程序的理由可能是最弱的”。
指导委员会的想法
在PEP上, Python指导委员会(可能是其最后一次正式行动之一,因为在12月16日选举产生了新的理事会)。华沙表示,已经在12月10日的会议上进行了讨论。理事会建议将PEP分为两部分,一部分适用于该语言的所有实现,并将提供在运行时确定限制的方法;另一部分是针对CPython的特定实现,但对该实现有限制。此外,“我们鼓励PEP的作者和支持者收集实际的绩效数据,以帮助我们评估PEP是否是一个好主意。”
Shannon仍然怀疑用“少量优化”来判断PEP是正确。不可能对所有无限可能的优化都加上数字,但也“不可能完美地预测哪些限制可能限制未来的可能的应用”。不过,他也同意,提出受限制的示例优化和应用程序将很有用。
在另一条主题中,Shannon要求提供反馈意见和建议,并提供具体细节。他还想知道,他选择一个数字作为限制(主要是作为记忆的辅助手段)的想法是否重要。又一些人认为,由于各种原因选择一个数字是不合理的。正如D' Aprano所说的那样,没有人需要记住这些限制,因为它们无论如何都应该很少会受到限制,而且应该有一种在运行时获得它们的方法。除此之外,对于嵌套括号、递归深度等现在还没有、将来也不会用到一百万行。
Paul Moore也认为单一的限制值并不重要,尽管他赞成为任何限制选择整数,而不是根据实现细节进行选择。他可能还总结了大多数人是如何看待这个想法的:
“我的观点是,我反对任何没有显示出好处的限制。我不在乎有多少好处,尽管我希望限制的影响与好处的水平保持一致。实际上,这意味着我认为这个提议是落伍的。我更希望这项提案的定义是‘如果我们强加这样或那样的一个限制,我们将能得到一个收益’。”
这就是现在的情况。指导委员会似乎对这个一百万行代码的限制很感兴趣,因为它在初期就接受了PEP,尽管该委员会的利益可能与Shannon的观点并不完全一致。然而,定义不清的限制,以及如果超过这些限制会发生什么的不明确语义,将对任何人都没有什么好处。对CPython的规范和对整个语言的其他API进行一些收紧将是很好的一步。它可能允许那些感兴趣的人在CPython的实验分支中调整值,以测试一些优化可能性。
原文链接:https://lwn.net/Articles/807218/
(*本文为AI科技大本营编译文章,转载请微信联系1092722531)
◆
精彩推荐
◆
点击阅读原文,或扫描文首贴片二维码
所有CSDN 用户都可参与投票和抽奖活动
加入福利群,每周还有精选学习资料、技术图书等福利发送
推荐阅读
被追捧为“圣杯”的深度强化学习已走进死胡同
阿里达摩院2020趋势第一弹:感知智能的“天花板”和认知智能的“野望”
基于机器学习场景,如何搭建特征数据管理中台?
从LeNet到GoogLeNet:逐层详解,看卷积神经网络的进化
召回→排序→重排:技术演进趋势的深度之旅,2020 必备!
如何写出让同事膜拜的漂亮代码?
2019最烂密码榜单出炉,教你设置神级密码
GitHub Action 有风险?!
骗了马云 10 亿被骂 4 年后,院士王坚留下 4 条人生启示
万字长文回望2019:影响区块链行业发展的9大事件
你点的每个“在看”,我都认真当成了AI
相关文章:

网吧电影客户端Realplayer的装配问题
网吧电影客户端Realplayer的装配问题 作者: 出处:网吧联盟 ( 20 ) 砖 ( 22 ) 好 评论 ( 1 ) 条 进入论坛 更新时间:2005-11-24 16:54关 键 词:网吧阅读提示:一般有过开网吧经验的朋友,应当知道如何让自己的realplayer播放器支…

基于Servlet+JDBC+Bootstrap+MySQL+AJAX权限管理系统项目实战教程
项目简介 权限系统一直以来是我们应用系统不可缺少的一个部分,若每个应用系统都重新对系统的权限进行设计,以满足不同系统用户的需求,将会浪费我们不少宝贵时间,所以花时间来设计一个相对通用的权限系统是很有意义的。 本系…

Windows客户端C/C++编程规范“建议”——表达式和运算
4 表达式和运算 4.1 比较操作中将常量设置为左值 等级: 【推荐】说明:编写代码时,如果将常量设置为右值。可能因马虎将“”写成“”导致逻辑错误。这种场景下,编译器是不会报错的,代码检查也比较容易被忽视。例子&…
GitHub标星1.5w+,从此我只用这款全能高速下载工具
「免费学习 60 节公开课:投票页面,点击讲师头像」作者 | Rocky0429来源 | Python空间(ID:Devtogether )大家好,我是 Rocky0429,一个喜欢在网上收集各种资源的蒟蒻...网上资源眼花缭乱,下载的方…

CSS text-transform 属性
定义 text-transform 对元素中的字母进行控制。 继承性:Yes 说明 这个属性会改变元素中的字母大小写,而不论源文档中文本的大小写。如果值为 capitalize,则要对某些字母大写,但是并没有明确定义如何确定哪些字母要大写,…

SeaJS基本开发原则
SeaJS基本开发原则 在讨论SeaJS的具体使用前,先介绍一下SeaJS的模块化理念和开发原则。使用SeaJS开发JavaScript的基本原则就是:一切皆为模块。引入SeaJS后,编写JavaScript代码就变成了编写一个又一个模块,SeaJS中模块的概念有点类…

SMS主站点配置详细图解:Sms2003系列之二
SMS主站点配置在上一篇文章中,我们介绍了如何进行SMS2003+SP2的部署。本文中,我们将介绍如何进行SMS主站点的配置。在SMS中,站点(site)定义并包含了所有SMS管理的对象。当我们第一次安装SMS时,实际安装的是一个SMS站点…
2019,不可错过的NLP“高光时刻”
作者 | Elvis译者 | 凯隐、夕颜出品 | AI科技大本营(ID: rgznai100)【导读】对自然语音处理(NLP)领域而言,2019年是令人印象深刻的一年,本文将回顾2019年NLP和机器学习领域的重要事件。内容 主要集中于 NLP…

Windows客户端C/C++编程规范“建议”——结构
5 结构 5.1 不要使用goto 等级: 【必须】说明:在大型项目中,goto的滥用会导致灾难性后果。因为我们程序中一般不存在从一个函数体内部跳转到另一个函数体内部的场景,所以我们可以将跳转控制在函数内部,从而避免灾难。…

WinForm容器内控件批量效验是否允许为空?设置是否只读?设置是否可用等方法分享...
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chinahuyong/article/details/47395633 WinForm容器内控件批量效验是否允许为空?设置是否只读?设置是否可用等方法分享 在WinForm程序中,我…
“不会Linux,怎么当程序员?”骨灰级程序员:干啥都不行。
说起优秀程序员的必备技能,我想大家都可以说很多,比如:数据结构、算法、数学、编程语言等等。但是,你可能会忽略了每一个程序员都应该掌握的技能:Linux。想一想,我们日常学习、求职、工作场景的中ÿ…

与空连接相关的几条命令
1)建立空连接:net use \\IP\ipc$ "" /user:"" (一定要注意:这一行命令中包含了3个空格) 2)建立非空连接:net use \\IP\ipc$ "密码" /user:"用户名" (同样有3个空格)3)映射默认共享:net use z: \\IP\c$ "密码" /u…

Windows客户端C/C++编程规范“建议”——宏
6 宏 6.1 减少宏的使用 等级: 【建议】说明:宏的使用,将使得调试变得麻烦。所以在设计和使用宏的时候,请确保宏的逻辑是阅读者不会去关心细节的行为。6.2 宏定义中字母需大写 等级: 【必须】说明:为了醒目…

Struts2中通配符的使用
1、准备工作 新建一个JavaWeb项目HelloWord,导入Struts2的.jar包,在Web.xml下配置Struts2的监听,在src下添加Struts2的配置文件struts.xml;将该项目部署到服务器(Tomcat)上,运行检查项目是否部署成功和其他错误&#x…
关于Spark NLP学习,你需要掌握的LightPipeline(附代码)| CSDN博文精选
作者 | Veysel Kocaman, Data Scientist & ML Researcher ANKIT CHOUDHARY翻译 | 赵春光校对 | 申利彬来源 | 数据派THU(*点击阅读原文,查看作者更多精彩文章)【导读】Pipeline具体来说是一个多阶段的序列,每个阶段由一个Transformer或者…

网络编程--ftp客户端的实现(c#版)
.net2.0对ftp有了一个很好的封装,但是确容易让人忽略ftp的真正内部实现,下面是我实现的ftp客户端的功能,其主要步骤是这样的:1、创建一个FtpWebRequest对象,指向ftp服务器的uri 2、设置ftp的执行方法(上传,下载等) 3、给FtpWebReq…

Windows客户端C/C++编程规范“建议”——文件
7 文件 7.1 正确使用#include 等级:【推荐】 说明:#include <>和#include “”导致编译器在搜索文件时,搜索的路径顺序不同。所以需要正确使用#include,以避免包含错了头文件。 语法形式操作带引号的形式预处理器按以下…
让你的网站支持 Emoji
SegmentFault有用户提出要支持Emoji表情输入,就研究了一下: 要记得备份数据库。 首先Mysql数据库在5.5.3之后开始支持utf8mb4字符集,所以mysql版本是5.5.3+的都可以设置让数据库存储Emoji表情,如果你的应用有移动端的&…

Windows客户端C/C++编程规范“建议”——变量和常量
8 变量和常量 8.1 尽量不要使用全局变量 等级: 【要求】说明:全局变量的滥用和goto的滥用一样,都是一种灾难。它将使得逻辑变得难以调试和控制。8.2 不涉及外部使用的全局变量需要使用static关键字修饰 等级: 【要求】说明&#…
机器学习模型五花八门不知道怎么选?这份指南告诉你
作者 | LAVANYA译者 | 陆离编辑 | 夕颜出品 | AI科技大本营(ID: rgznai100)【导读】在本文中,我们将探讨不同的机器学习模型,以及每个模型合理的使用场景。一般来说,基于树形结构的模型在Kaggle竞赛中是表现最好的&…

WinAPI: FlattenPath、WidenPath
不管什么曲线命令, 到来路径中都会变成 Bezier 线; 也就是说路径中只有直线和 Bezier 线.FlattenPath 和 WidenPath 都能够把路径中的 Bezier 线转换为近似的直线; 不同的是: 用 WidenPath 转换后貌似加宽了线, 其实它是转换成了一个包围路径的新路径(类似区域).本例效果图:代码…

Android - 小的特点 - 使用最新版本ShareSDK手册分享(分享自己定义的接口)
前太实用Share SDK很快分享,但官员demo快捷共享接口已被设置死,该公司的产品还设计了自己的份额接口,这需要我手动共享。 读了一堆公文,最终写出来,行,废话,进入主题。 之前没实用过ShareSDK分享…
结合Flink,国内自研,大规模实时动态认知图谱平台——AbutionGraph |博文精选
作者 | Raini出品 | 北京图特摩斯科技 (www.thutmose.cn)(*点击阅读原文,查看作者更多精彩文章)Flink:目前最受关注的大数据技术,最活跃 Apache 项目之一。AbutionGraph:北京图特摩斯科技自研的…

Windows客户端C/C++编程规范“建议”——风格
9 风格 9.1 优先使用匈牙利命名法 等级: 【推荐】说明:该方法由微软总设计师设计。Windows上编程最好遵从该标准。详细介绍见:http://zh.wikipedia.org/wiki/%E5%8C%88%E7%89%99%E5%88%A9%E5%91%BD%E5%90%8D%E6%B3%959.2 变量名结合使用匈牙…

使用GIF(仅限Delphi2007)
-----------uses GIFImg; procedure TForm1.FormCreate(Sender: TObject); begin // 先在窗体上放一个 TImage 组件:Image1; Image1.Picture.LoadFromFile(C:\Example.gif); // AnimationSpeed 设定动画速度,值越大,速度越快…

使用Depth Texture
使用Depth Textures: 可以将depth信息渲染到一张texture,有些效果的制作会需要scene depth信息,此时depth texture就可以派上用场了。 Depth Texture在不同平台上有不同的实现,并且原生的支持也不一样。 UnityCG.cgin…

Exchage 2007 Client Application Functions(2) -- 如何收取邮件
上一篇介绍的Exchange2007客户端程序中怎么发送邮件。现在,我来简单介绍一下怎么收取邮件。来看代码:publicHashtable GetAllMails(DateTime StartDate, DateTime EndDate) { try { if (null this.m_esb) …

VC开发Windows客户端软件之旅——前言
从第一次拖着行李入京找活,至今已工作若干年了。这些年一直追逐自己的梦想,跑过三个城市,换了三份工作,认识了很多业内的朋友。和朋友们闲聊时,发现很多人都已经不再做客户端软件了。有的转去做管理,有的转…
代替Mask R-CNN,BlendMask欲做实例预测任务的新基准?
「免费学习 60 节公开课:投票页面,点击讲师头像」作者 | Hao Chen、Kunyang Sun、Zhi Tian、Chunhua Shen、Yongming Huang、Youliang Yan译者 | 刘畅编辑 | Jane出品 | AI科技大本营(ID:rgznai100)【导读】实例分割是…

如何让ie 7 支持box-shadow
box-shadow是一个很好用并且也常用的css 3属性,但是,如果我们要保证它能在ie 8及更低的版本下运行的话,需要借助一些其他的插件或文件。在这里我主要讲一下,如何用PIE.htc来解决ie 7不支持box-shadow。 代码如下: <…