在刚刚过去的 2018 年里,要说最热门的科技领域是哪一个?毋庸置疑的是,人工智能必排在前列;而要论编程语言界,最流行的编程语言是谁?那非 Python 莫属。2018 年 8 月,根据一年一度的 IEEE Spectrum 编程语言来看,Python 一路高歌猛进,位居 48 种编程语言之首。不仅如此,在本月最新的 TIOBE 排行榜中,Python 再次超越 C++,位居排行榜前三甲,其受欢迎程度不言而喻,但就在此时,Python 却惨遭开发者嫌弃了,而这究竟是怎么一回事?

作者 | Neal Krawetz
译者 | 弯月
责编 | 屠敏
来源 | CSDN(ID:CSDNnews)

以下为译文:

有时候我会跟一些搞技术的朋友们出去吃饭,当然我们会愉快地讨论技术。我们讨论自己项目、讨论新鲜事、讨论各种技术问题。最终不可避免地会讨论到编程语言。有人就会说“我又得改 Java 代码了。我恨 Java。”(抱歉了 Kyle……)(其实十多年前我们就给 Kyle 起了个绰号“Java 小子”。)另一个人就会谈起某个古老的无所不包的 Shell 代码,那段代码无人敢碰。

至于我,嗯……我的话一出口众人都惊呆了:我讨厌 Python。我讨厌它是有原因的。如果我能用 C 重写某段 Python 代码,那我一定会重写的。

但我吼完之后,Bill 幽默地补刀:“那你内心里是怎么看 Python 的,Neal?”所以就有了这篇文章。谨以此文献给 Bill。

下面是我列出的“8 个理由说明 Python 很糟糕”。

版本

默认的 Linux 安装很可能会带有多个版本的 Python。很可能会同时拥有 Python 2 和 Python 3,而且很可能同时拥有不同的子版本,如 3.5 和 3.7。理由是:Python 3 不能与 Python 2 完全兼容。即使一些子版本号也会造成无法后向兼容。

我不反对给语言添加新功能,甚至退役一些旧版本也无所谓。但是,不同的软件需要不同的 Python。我给 Python 3.5 编写的代码不能在 Python 3.7 上正常运行,除非我专门将其移植到 3.7。许多 Linux 开发者都认为移植不值得,所以 Ubuntu 就同时带有 Python 2 和 Python 3,因为不同的核心功能需要不同的 Python 版本。

缺乏向后兼容和版本之间的割裂通常是死亡的信号。Commodore 是世界上最早制造家用电脑的厂商之一(远在 IBM PC 和苹果之前)。但 Commodore 的 PET 没法与后继的 Commodore CBM 电脑兼容。而且,CBM 也不兼容 VIC-20、Commodore-64、Amiga 等。所以,你只能花大把时间把代码从一个平台移植到另一个平台,否则就要完全放弃那个平台。(现在 Commodore 在哪儿?它早就因为用户放弃它的平台而死了。)

同样命运的还有 Perl。Perl 曾经非常流行。但 Perl 3 问世时,它与很多 Perl 2 代码都不兼容。社区对此意见很大,只有好的代码得到了移植,其他代码都被抛弃了。然后 Perl 4 出现时又发生了同样的事情。Perl 5 出现时,很多人干脆换到了其他更稳定的编程语言。现在,只有很少一部分人仍然在使用 Perl 来维护现有的 Perl 项目。已经没有任何新项目使用 Perl 了。

同样,Python 的每个版本的代码也都是不一样的,社区也不得不维护旧的版本。因此就要不断维护一大堆陈旧已失去活力的 Python 代码,因为没人想把它们移植到新版本。据我所知,现在没有人在 Python 2 上写新代码,但现有的 Python 2 又不得不维护,因为人们不愿意将它们移植到 Python 3。在 Python 的官方网站上,Python 2.7、3.5、3.6 和 3.7 的文档都在维护中,因为还有旧代码在使用这些版本,他们没办法放弃这些版本。Python 就像编程语言中的百足之虫,死而不僵。

安装

绝大多数软件包都可以通过 apt、yum、rpm 或某种安装方式获得最新的代码。而 Python 则不一样。你无法知道 apt-get install python 会给你装什么版本,很可能这个版本跟你的代码都不兼容。

所以,必须选择你所需版本的 Python 来安装。我参与过的一个项目使用的是 Python,但必须使用 Python 3.5(当时的最新版本)。最后我的电脑上安装了 Python 2、 Python 2.6、Python 3 和 Python 3.5。两个是操作系统自带的,一个是为项目安装的,另一个来自我安装的某个不相关的软件。虽然它们都是 Python,但并不是完全一样。

要想给 Python 安装软件包,应该使用“pip”命令。(pip 的意思是“PIP Install Packages”,因为有人觉得递归的缩写很有意思。)但由于系统上有多个版本的 Python,你必须要注意使用正确版本的 pip。否则,pip 可能运行的是 pip 2 而不是你需要的“pip 3.7”。(如果 pip 3.7 这个命令不存在,你还得指定正确的路径。)

有个团队成员建议我,我应该配置自己的环境,这样一切都能使用 Python 3.5 的版本。这种方法很好,但后来我的另一个项目需要 Python 3.6 就出现麻烦了。两个并行的项目使用了不同版本的 Python……嗯,这还不够迷惑。(表示讽刺的表情是什么来着?)

pip 安装程序会把文件放到用户的本地目录中。系统范围上的软件包不能使用 pip 安装。而且你也不能使用 sudo pip,因为那会搞乱你整个电脑!因为使用 sudo 会在整个系统级别安装软件,一些软件会安装到错误的 Python 版本,一些会留在你的主目录中但却属于 root,导致以后的非 sudo pip 命令由于权限问题而出错。所以不要使用 sudo pip。

另外,谁负责维护这些 pip 模块?是社区。也就是说,没有固定的拥有者,也没有强制的保证或审计。今年早些时候,某个版本的 PyPI 被发现有个后门,会盗取 SSH 密码。这种事情根本不奇怪。(同样的原因我也不用 Node.js 和 npm,我不相信他们的社区软件仓库。)

语法

我极其推崇代码的可读性。初看起来,Python 代码似乎可读性很高。没错,不过条件是你不要用它来开发大型代码。

绝大多数编程语言都有某种标识来表明作用域——即函数何时开始何时结束,动作包含在一个条件语句中,变量定义的范围,等等。不论是 C、Java、JavaScript、Perl 还是 PIP,大家都使用{ ... } 为复杂的代码定义作用域,而 Lisp 使用(...)定义作用域。Python 呢?Python 使用空格。如果需要为一段复杂的代码定义作用域,就必须要缩进接下来的几行。缩进结束就表明作用域的结束。

我第一次看到 Python 代码时,我认为使用缩进定义作用域是个不错的想法。但是,这种方式有个巨大的缺点。这种方式可以写出很深的嵌套,但代码行也会变得很宽,导致在文本编辑器中折行。长的函数和长的条件动作很难找出作用域的开始和结束。而且,只要你数错了空格,或者在某行开头放了三个空格而不是四个空格,那你需要花上几个小时的调试才能找到问题所在。

在其他语言中书写调试代码时,我习惯不放任何缩进。这样我就能迅速浏览到代码,并在调试结束之后很容易地找到调试代码并删掉。但用 Python 呢?任何缩进不正确的行都会导致缩进错误。也就是说,调试代码必须混合到正式代码中。

包含

大多数编程语言都有一些方法可以包含其他代码块。C 语言有“#include”。PHP有'include','include_once','require'和'require_once'。而 Python 有“import”。

Python 的导入允许包括整个模块,模块的一部分或模块中的特定功能。想知道哪些东西可以导入,并没有什么直观的办法。使用 C,你可以查看 /usr/include/*.h。但是用 Python?最好使用 'python -v' 列出它看起来的所有位置,然后搜索该列表中每个目录和子目录中的每个文件。我曾经看到我喜欢 Python 的朋友 grep 标准模块来寻找他们想要导入的东西。这是真事。

导入功能还允许用户重命名导入的代码。它们基本上定义了一个自定义命名空间。乍一看,这似乎很不错,但最终会影响可读性和长期支持。重命名模块非常适合小脚本,但对于长程序来说真的很糟糕。使用 1-2 字母命名空间的人,例如“import numpy as n”应该拖出去枪毙(或强制将其所有代码转换为 Perl 5)。

但这不是最糟糕的部分。对于大多数语言,include 一段代码只会包含代码。一些语言(如面向对象的 C ++)会在存在全局构造函数的情况下执行代码。类似地,一些 PHP 代码可能会定义全局变量,因此导入可以运行代码——但通常人们认为这不是一种好做法。相比之下,许多 Python 模块包括在导入期间运行的初始化函数。你不知道哪部分代码在运行,你不知道它在做什么,你甚至可能都注意不到。哦,有一种情况你会注意到——那就是出现命名空间冲突的时候,在这种情况下,你需要花很多时间来追踪原因。

命名法

在其他所有语言中,数组都称为“array”。在 Python 中,它们被称为“list”。关联数组有时称为'hash'(Perl),但 Python 称之为'dict'。 Python 似乎没有使用在计算机和信息科学领域的常用术语。

然后是库的名称。 PyPy,PyPi,NumPy,SciPy,SymPy,PyGtk,Pyglet,PyGame ...(是的,第一个和第二个的读音相同,但是它们是完全不同的东西。)我知道'py'表示 Python。但 py 放在开头还是结尾能不能有个固定的写法呢?

一些常见的库只是放弃了类似双关语的“Py”命名约定。这包括 matplotlib,nose,Pillow 和 SQLAlchemy。虽然一些名称可能暗示库的目的(例如,“SQLAlchemy”包含 SQL,所以它可能是一个 SQL 接口),但其他名称只是随机的单词。如果你不知道“BeautifulSoup”是干什么的,你能从名称中看出它是一个 HTML / XML 解析器吗? (顺便说一句,BeautifulSoup 有很好的文档和易于使用。如果每个 Python 模块都是这样的,我不会抱怨太多。不幸的是,这并不是常态。大多数 Python 库的文档写得都很差。 )

总的来说,我将 Python 视为具有可怕且不一致的命名约定的库的集合。我有一个常见的抱怨,开源项目通常有可怕的名字。除非你知道这个项目,否则你永远不知道它的名字是什么。除非你知道要寻找什么,否则只能期待于偶然遇到某个别人提起的库了。而且大多数 Python 库都强化了这种负面的批评。

怪癖

每种语言都有它的怪癖。C 语言使用&和*来访问地址空间和值的做法很奇怪。 C 还有使用 ++ 和 -- 来表示递增/递减的快捷方式。在 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 中的引号使用方法再下结论。

对象的引用传递

大多数编程语言都用值方式传递函数参数。如果函数改变了值,则改变不会影响到调用的代码。但正如我已经解释过的那样,Python 在这方面依然与众不同。 Python 默认使用引用方式传递参数。这意味着更改参数可能会导致原始值的改变。

这是过程式编程、函数式编程和面向对象编程语言之间的重大差异之一。如果每个变量都是通过对象引用传递的,并且对变量的任何更改都会影响到任何使用该变量的地方,实际上就相当于一切都使用了全局变量。针对一个变量使用不同的名称实际上都是同一个对象,所以跟使用全局变量没什么区别。C 程序员很久以前就知道,全局变量是邪恶的,不应该被使用。

Python 中要想按值传递变量就必须使用额外的方式。简单地写下“a = b”只会给同一个对象起另一个名字,而不会将 b 的值复制到 a 中。如果你确实要复制该值,则需要使用复制功能。通常是用“a = b.copy()”。但是请注意我说的是“通常”。并非所有数据类型都支持“复制”的原型,还有可能复制功能不完整。在这些情况下,你必须使用一个名为“copy”的独立库,即“a = copy.deepcopy(b)”。

局部命名

根据使用的库或函数对程序进行命名,是常见的编程技巧。例如,如果我要对使用某个名为"libscreencapture.so”的库的截屏程序进行测试,我会把我的程序叫做“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 的兴趣。

我的朋友经常提起 Python 那些非常酷的函数库。我也同意,某些函数库非常有用。例如, BeautifulSoup 就是我用过的最好的 HTML 解析器之一,NumPy 简化了多维数组和复杂的数学计算,TensorFlow 在机器学习方面非常有用。但我不会只因为 TensorFlow 或者 SciPy 就用 Python 编写一个大而全的程序。我不会放弃可读性和可维护性,这样做不值得。

通常,我在批评某个东西时也会写一些正面的东西。比如,我的博客上“开源很糟糕”后面写了一篇“开源很不错”,批评完 ffmpeg 的局限性之后也会特别提到它是最优秀的视频处理库。但 Python 我写不出优点列表来,因为我真的觉得它太糟了。

原文:

https://www.hackerfactor.com/blog/index.php?/archives/825-8-Reasons-Python-Sucks.html

作者:Neal Krawetz,在 Texas A&M University 获得计算机科学的博士学位,创立了 HackerFactor Solutions,专注于非传统的计算机法医学、在线评测、网络和计算机安全等。

本文为 CSDN 翻译,如需转载,请注明来源出处。

公开课预告

强化学习

本课程是一次理论+实战的结合,将重点介绍强化学习的模型原理以及A3C模型原理,最后通过实践落实强化学习在游戏中的应用。

推荐阅读:

  • 刘铁岩谈机器学习:随波逐流的太多,我们需要反思

  • 清华首批7门标杆课程,到底有多牛?

  • 老程序员肺腑忠告:千万别一辈子靠技术生存!

  • Java JDK 收费,Android 也坐不住了,程序员们该咋办?

  • 程序员有话说|外包程序员,混得最差劲

  • IPFS 深入浅出:从《黑镜》说起

  • 云计算的概念 - 初识云计算知识专栏(1)

  • 这个用Python编写的PDF神器你值得拥有!

  • 春运抢票靠加速包?试试这个Python开源项目吧

频频霸榜的Python,竟遭开发者嫌弃!相关推荐

  1. 频频霸榜的 Python,竟遭开发者嫌弃!

    在刚刚过去的 2018 年里,要说最热门的科技领域是哪一个?毋庸置疑的是,人工智能必排在前列:而要论编程语言界,最流行的编程语言是谁?那非 Python 莫属.2018 年 8 月,根据一年一度的 I ...

  2. 中文repo“霸榜”GitHub Trending,国外开发者不开心了

    编译整理 | 一一 出品 | AI科技大本营(ID:rgznai100) 近日,一位叫Balazs Saros 的国外开发者在Medium上发表了一篇名为"Chinese repos are ...

  3. 安兔兔发布9月份Android性能榜:855霸榜,华为竟垫底

    昨日,安兔兔官微发布了2019年9月份国内Android手机性能排行榜.尽管现在网友粉丝都笑称该排行榜不靠谱,但每次选购手机或者在朋友面前比较还是会拿这个说事,你身边有这样的朋友吗? 据了解,排行榜中 ...

  4. github上7个霸榜的Python资源库

    1.Learn-Python https://github.com/trekhleb/learn-python   可以作为初学者和中级学习者的Python资源集合.该项目使用一组Python脚本来涵 ...

  5. GitHub 长期被中国人“霸榜”?看完榜单我呆了...

    你平常逛 GitHub 都会看什么? 作为「技术行业观察者」的我,平时经常会逛 GitHub 找选题,最近我又在上面发现了很多宝藏...或者叫大宝箱... 以下正文: 随着 GItHub 在国内的普及 ...

  6. 极客日报第 42 期:开发者抢茅台软件霸榜GitHub;双十一“套路”多,京东天猫唯品会被罚

    文章目录 一.互联网快讯 二.程序员专属 三.Github 每日精选 四.CSDN 社区优质博文精选 一.互联网快讯 1.双十一"套路"多,京东.天猫.唯品会被罚! 针对" ...

  7. python京东抢购 github_两天狂揽 4k+ Star,抢茅台 Python 脚本霸榜 GitHub

    原标题:两天狂揽 4k+ Star,抢茅台 Python 脚本霸榜 GitHub 声明:本文已获得 开源前哨 授权 某东抢茅台脚本在 GitHub 连续霸榜 30 日,前哨君在刷 GitHub 的时候 ...

  8. 中国人长期“霸榜”GitHub,国外开发者发文控诉

    本文转载自AI科技大本营(ID:rgznai100) 近日,一位叫Balazs Saros 的国外开发者在Medium上发表了一篇名为"Chinese repos are ruining t ...

  9. GitHub被中国人霸榜!国外开发者不开心了

    点击上方"朱小厮的博客",选择"设为星标" 做积极的人,而不是积极废人 来自:OpenSourceTop 原文:http://uee.me/aXbHj 近日,一 ...

最新文章

  1. 在cmd的方式下,简化mysql的输入的方法
  2. Docker1.12.1之swarm集群搭建与使用
  3. HotSpot VM运行时01---命令行选项解析
  4. IOS开发基础之英雄展示完整版
  5. LeetCode 986. 区间列表的交集
  6. 计算机与编程导论,计算机科学与编程导论
  7. Js模块化开发的理解
  8. spdlog linux编译出错,Linux下编写Makefile引入第三方库
  9. c语言单位换算转换程序,c语言时间换算(c语言时间换算过n秒)
  10. rabbitmq启动报错,TCP connection succeeded but Erlang distribution failed
  11. 11.1.4 子线程与主线程通信实例
  12. 中国石油沥青行业市场供需与战略研究报告
  13. 兵法三十六计是哪些?
  14. html中onfocus作用,HTML onfocus用法及代码示例
  15. 数据治理【数据安全管理】
  16. 大数据文字游戏_移动的大数据指南:千字以内的文章传播率最高
  17. android商店账号密码错误,android app 自定义签名出现错误:Keystore was tampered with, or password was incorrect...
  18. css 选取第一个标签元素
  19. python爬虫入门——QQ音乐歌手照片及歌曲列表爬取
  20. 中国互联网20周年谈----GITC 2014

热门文章

  1. JBL无所不能与IPhone4、IPad2的完美盛宴
  2. android写代码截屏微信,android 模仿微信头像裁剪
  3. 数值分析第一次作业-牛顿迭代法求解二元非线性方程组
  4. Centos7 安装 telnet 服务
  5. ubuntu16创建开机启动服务
  6. Linux shell 脚本报错:/bin/bash^M: bad interpreter: No such file or directory
  7. HTML 5中SEO可以用那些代码来做优化
  8. [转]使用设计模式改善程序结构(二)
  9. controlfile
  10. 第02章 PyTorch基础知识