点击上方 \公众程序员小乐\"大众关注"大众年夜众号, 星标或置顶一起发展
每天凌晨00点00分, 第一韶光与你相约
逐日英文

We don't need to meet again for we are just passers by.To forget is the best commemoration for each other.
很多人不须要再见,由于只是途经而已。遗忘便是我们给彼此最好的纪念。
逐日掏心话
走远了再转头看,很多人已经淡忘,只有很少的人牵连着我们的幸福与快乐,这才是我们真正要珍惜的地方。
来自:机器之心 | 责编:乐乐
程序员小乐(ID:study_tech)第 659 次推文 图片来自网络
昔日回顾:你不知道的 IDEA Debug 调试小技巧!
正文
本文作者有一群 geek 朋友,常常一起谈论技能话题,有时候也会商到编程措辞。「I hate Python」,作者表示。他对 Python 厌恶至极。纵然有现成的 Python 代码可用,他也甘心用 C 措辞重写。为了系统地吐槽 Python,作者专门写了这篇博客,细数 Python 的「八宗罪」。
这个话题已经在 Hacker News 上引发了热烈的谈论(评论 400+),感兴趣的读者可以去围不雅观或参与一下。
Hacker News 谈论:https://news.ycombinator.com/item?id=18706174
1. 版本
如果要安装一个默认的 Linux 操作系统,那你很有可能须要安装多个版本的 Python:Python2、Python3 乃至是 3.5、3.7。缘故原由在于:Python3 无法与 Python2 完备兼容。乃至一些用小数表示的版本(如 3.5、3.7)也明显缺少向后的兼容性。
我完备附和往编程措辞中添加新的功能,我乃至不介意淘汰一些旧的版本。但 Python 却要分开安装。我的 Python 3.5 代码不适用于 Python 3.7 安装版本,除非我特意将其导入 3.7。很多 Linux 开拓者都以为导出太麻烦,因此安装 Ubuntu 的时候会一并安装 Python2 和 Python3——由于有的核心功能须要前者,而有的须要后者。
向后兼容性的缺少和各不相谋的版本常日会为其敲响丧钟。Commodore 创造了第一批家用电脑(比 IBM PC 和苹果都要早很多)。但 Commodore PET 不能与后续的 Commodore CBM 兼容。CBM 又不与 VIC-20、Commodore-64、Amiga 等兼容。因此,你要么选择花很多韶光将代码从一个平台导到另一个,要么选择放弃这个平台。(Commodore 本日何在?早被用户抛弃凉凉了……)
类似地,Perl 也火过一阵。但 Perl3 与 Perl2 的很多代码也不兼容。社区骂声一片,于是一些好的代码导了出来,其他的则被抛弃了。Perl4 也是如此。等 Perl5 出来的时候,人们干脆改用另一种更稳定的编程措辞。如今,只有一小部分人还在频繁利用 Perl 来坚持之前的项目。但已经没有人用 Perl 创建新的大项目了。
同理,Python 的每个版本也都存在谷仓效应。之前的版本还要留着,终极造成手里有一堆旧的无用 Python 代码,由于大家都不想花韶光将其移到最新版上。据我所知,没有人为 Python2 创建新代码了,但我们还留着它,由于没有人想将所需代码移到 Python3.x 中。Python 2.7、3.5、3.6、3.7 的文档都还在 Python 官网上积极掩护着,由于他们无法下决心弃用之前的代码。Python 就像一种僵尸编程措辞——已经去世掉的部分还在以行尸走肉的办法存在着。
2. 安装
很多软件包都可以帮你轻松地运行 apt、yum、rpm 或其他一些安装库,并得到最新版本的代码。但 Python 并非如此。如果用「apt-get install python」安装,你都不知道自己安的是哪个版本,它可能也无法与你所需的所有代码兼容。
因此,你要安装你须要的那版 Python。我的个中一个项目用到 Python,但必须用 Python3.5。以是末了,我的电脑安装了 Python2、Python2.6、Python3 及 Python3.5。个中两个来自操作系统,一个用于项目,其余一个做事于出于其他缘故原由安装的无关软件。虽然都是 Python,但此 Python 非彼 Python。
如果你想安装 Python 包,你该当利用「pip」(Pip Installs Packages)。但由于系统上有一堆 Python,你要把稳利用精确版本的 pip。否则,「pip」可能运行「pip2」,而不是你须要的「pip3.7」。(如果名称不存在,你须要为 pip3.7 指定明确的真实路径)
一位队友建议我配置自己的环境,这样的话每种软件都可以利用 Python3.5 的 base 环境。在我须要用 Python3.6 开展另一个项目之前,这种做法是非常行得通的,但是须要 Python 3.6 就得创建其余一个环境。两个项目,两版 Python,一点都不会混,真的(用生命在假笑)。
pip 安装程序将文件放置在用户确当地目录。安装系统级的库时不用 pip。Gawd 不许可你在运行「sudo pip」时出错,由于那会毁了你的全体电脑!
运行 sudo 可能会使一些软件包在系统级别安装,有些是为缺点版本的 Python 安装的,而你的主目录中的一些文件可能终极归 root 所有,因此未来的非 sudo pip 安装可能会因权限问题而失落败。不要这样做。
这些 pip 模块由谁来掩护呢?当然是社区。也便是说,没有明确的所有者,也没有逼迫性的来源链或任务链。今年早些时候,PyPI 的一个版本中创造了一个盗取 SSH 凭据的后门。这也是猜想之中。(出于同样的缘故原由,我不用 Node.js 和 npm;我不信赖他们的社区项目。)
3. 句法
我非常主见代码的可读性要强。乍一看,Python 的可读性彷佛不错。但当你开始创建大型代码库的时候你就不会这么想了。
大多数编程措辞利用某种符号来标识范围——函数的开始和结束位置、条件语句中包含的操作、变量的定义范围等。C 措辞、Java、JavaScript、Perl 和 PHP 都用 {...} 来定义范围,Lisp 利用 (...)。Python 呢?它用空格!
如果你要定义繁芜代码的范围,你可以缩进接下来的几行代码,缩进结束时,该范围也截止。
Python 手册说,你可以用任意数量的空格或制表符来定义范围。但是,每次缩进最好利用四个空格!
如果你想缩进两次进行嵌套,利用八个空格!
Python 社区已经对此进行标准化,纵然 Python 手册中并没有明文规定。这个社区就喜好用四个空格。以是,除非你不打算将自己的代码向任何人展示,否则的话每次缩进最好用四个空格。
我第一次看到 Python 代码时,以为用缩进来定义范围还挺好的,但这么做有一个巨大的毛病。你可以进行深度嵌套,但这么做使得每一行都会很长,导致不得不在文本编辑器中换行。较长的函数和条件语句可能会使开始和结束范围很难匹配。而且当你欠妥心把三个空格当成四个空格,还随意马虎涌现打算缺点,进而花几个小时来调试和追踪。
对付其它措辞,我已经养成了调试代码不带任何缩进的习气。这样,我可以快速浏览代码,然后轻松地识别和删除调试代码。但 Python 呢?任何没有适当缩进的代码都会产生缩进缺点。
4. includes
大部分编程措辞都有办法导入其它代码块。比如,C 措辞用「#include」,PHP 措辞可以用「include、include_once、require、require」。而 Python 用的是「import」。
Python 可以导入全体模块、模块的一部分或模块中的特定函数。C 措辞?你可以查看「/usr/include/」。Python 的话,最好用「python -v」列出所有路径,然后从列表中搜索每个目录和子目录中的每个文件。我有些朋友很喜好 Python,但我看到他们想导入东西时,总得浏览标准模块。
导入功能还许可用户重命名导入的代码。它们基本上定义了一个自定义的命名空间。乍一看,你会以为挺不错的,但这终极会影响可读性和长期支持。重命名对付较小的脚本来说还是不错的,但对付长期项目来说真的不适用。那些利用 1-2 个字母作为命名空间(比如「import numpy as n」),而且还不按约定俗成的办法来命名的,切实其实该当拉出去枪毙!
这还不是最糟糕的。大部分编程措辞 include 代码的时候就只是导入代码而已。如果有一个带有布局函数的全局工具,有些措辞,如面向工具的 C++可能会实行代码。类似地,有些 PHP 代码可能会定义全局变量,以是导入可以运行代码——但这种做法常日被认为很糟糕。比较之下,很多 Python 模块包含在导入期间运行的初始化函数。你不知道在运行的是什么,它要干什么,你乃至可能不会把稳到。除非存在命名空间冲突,如果这样就好玩了,你得花很多韶光来探求缘故原由。
5. 命名法
在其它措辞中,数组(array)直接称之为'arrays',但是在 Python 中,它们被称为 'lists'。关联数组在某些地方被称为 'hash' (Perl),但是 Python 将其称为「字典」(dictionary)。Python 彷佛完备按照自己的节奏来,不该用打算机科学和信息科学领域的常见术语。
此外,Python 库的命名也有问题。PyPy、PyPi、NumPy、SciPy、SymPy、PyGtk、Pyglet、PyGame……(前两个库的发音一样,但是它们的功能完备不同)。我理解「py」表示 Python,但是它们就不能统一涌如今前面或后面吗?
一些常见库放弃了类似双关语的「Py」命名约定,包括 matplotlib、nose、Pillow和 SQLAlchemy。虽然有一些命名可能暗示其目的(如 SQLAlchemy 包含 SQL,以是它可能是一个 SQL 接口),但是其它的可能只是随机的单词。如果你不知道「BeautifulSoup」这个库是干什么的,那么你能从命名看出来它是一个 HTML/XML 解析器吗?不过,BeautifulSoup 有很完善的文档且易于利用,如果每一个 Python 模块都这样,我也就不抱怨了,但是大多数 Python 库的文档非常烂。
总的来说,我认为 Python 是一个具有不一致命名约定的函数库凑集。我常常抱怨开源项目的命名非常恐怖。除非你知道这些项目在干什么,否则你从命名本身中什么都看不出来。除非你知道在探求什么样的库,不然只能通过别人有时提及的名字或有时的机会创造一些库。大多数 Python 库加重了这种征象,也加重了 Python 的负面体验。
6. 奇怪的操作
每种措辞都有自己比较奇特的操作。C 措辞中利用 & 和 获取地址空间和值的命名法非常奇怪。C 措辞中还有用 ++ 和—实现 increment/decrement 的捷径。Bash 措辞中,在引用特定字符(如用于正则表达式的圆括号和句号)时须要一贯考虑「什么时候利用转义符 (\)」。JavaScript 兼容性有问题(并非每个浏览器都支持所有有用的功能)。但 Python 的奇怪操作比我见过的其他措辞都多。如:
在 C 措辞中,双引号里的是字符串,单引号里的是字符。
在 PHP 和 Bash 中,两种引号都能包含字符串。但是,双引号里的字符串可以嵌入变量。比较之下,单引号的字符串是笔墨;任何嵌入的类似变量的名称都不可扩展。
在 JavaScript 中,单引号和双引号没什么差异。
在 Python 中,单引号和双引号也没有什么差异。但是,如果你想让字符串跨行,就得用三重引号,如\"大众\公众\"大众string\"大众\"大众\"大众 或 '''string'''。如果你想用二进制,那你须要优先选择带有 b(b'binary')或 r(r'raw')的字符串。有时你要用 str(string) 把字符串转换为字符串,或利用 string.encode('utf-8') 将其转换为 utf8 格式。
如果你一开始认为 PHP 和 JavaScript 中的=、==、===有点奇怪,那等你用 Python 中的引号时可能不会这么想了。
7. 通过工具 Reference 通报
大多数编程措辞的函数参数通报是传值。如果函数改变了值,结果不会通报回调用代码。但正如我阐明过的,Python 偏偏要有所不同。Python 默认利用 pass-by-object-reference 来通报函数参数。这意味着改变源变量可能终极会改变值。
这是面向程序、函数和工具的编程措辞之间的最大差异。如果每个变量都由工具引用来通报,并且变量的任何变革都会改变所有的引用,那你可能利用的都是全局工具。通过不同的命名调用相同的工具不会改变工具,以是实际上它便是全局的。此外,正如 C 的程序员早就学到的,全局变量太恶心了,别用。
在 Python 中,你必须通过值来通报变量,例如「a=b」只是给相同的工具空间分配了另一个命名,但并没有复制 b 的值给 a。如果你真的想要复制 b 的值,你须要利用一个 copy 函数,常日是「a=b.copy()\"大众的形式。然而,把稳我说的是「常日」。不是所有数据类型都有一个「copy」原型,或者 copy 函数可能是不完全的。在这种情形下,你可以利用单独的「copy」库:\"大众a=copy.deepcopy(b)\"大众。
8. 本地命名
用所用的库或函数的名字来命名程序是常见的编程技巧。例如,如果我用一个叫做「libscreencapture.so」的 C 库来测试一个截屏程序,我会将该程序命名为「screencapture.c」并编译为「screencapture.exe」。
gcc -o screencapture.exe screencapture.c -lscreencapture
在 C、Java、JavaScript、Perl、PHP 等措辞中,这常日很有效,由于这些措辞可以轻易地辨别本地程序和资源库,它们有不同的路径。但 Python 呢?还是算了吧,千万别这样做。为什么?Python 会假定你首先要导入本地代码。如果我有一个名为「screencapture.py」的程序利用了「import screencapture」,那么它将导入自己而不是系统库。至少,你该当调用本地程序「myscreencapture.py」吧。
并非一无是处
Python 是一门非常盛行的编程措辞,有很多粉丝。乃至我的很多朋友都很喜好 Python。多年来,我和他们谈论过这些问题,每次他们都点头表示赞许。他们并不反对 Python 存在这些问题,只因此为这不敷以浇灭他们对这种措辞的激情亲切。
我的朋友常常提到那些非常酷的 Python 库。我赞许一些库非常有用。例如,BeautifulSoup 是我用过最好的 HTML 解析器之一,NumPy 使多维数组和繁芜的数学更随意马虎实现,而 TensorFlow 对付机器学习非常有用。但是,我不会由于喜好 TensorFlow 或 SciPy 而用 Python 创建单片程序。我不打算为了这些「蝇头小利」而放弃可读性和可掩护性,这不值得。
常日当我写一篇关于某个主题的批评时,我也会考试测验写一些积极的东西。但我没办法列出关于 Python 的好的方面,由于我真的认为 Python 很糟糕。
原文地址:
https://www.hackerfactor.com/blog/index.php?/archives/825-8-Reasons-Python-Sucks.html
欢迎在留言区留下你的不雅观点,一起谈论提高。如果本日的文章让你有新的启示,学习能力的提升上有新的认识,欢迎转发分享给更多人。
欢迎各位读者加入程序员小乐技能群,在公众年夜众号后台回答“加群”或者“学习”即可。
猜你还想看
阿里、腾讯、百度、华为、京东最新口试题搜集
从 Spring Cloud 看一个微做事框架的「 五脏六腑 」
学界:为代码自动添加注释,让 Java 程序的阅读和开拓更高效
在 JVM 眼中 .class 文件是什么样的?值得收藏!
关注微信"大众号「程序员小乐」,收看更多精彩内容
嘿,你在看吗?