转眼间,2018 年已进入倒计时阶段,回忆起这一年中编程语言界的发展,过得风生水起的语言非 Python 莫属。而它的火热和人工智能产业的爆发不无关系,但全局来看,得益于 AI 的 Python 并非止于 AI,Python 还在系统编程、多媒体应用、数据库编程、Web、爬虫等多个场景中均有应用。不仅如此,这一年的 Python 在 TIOBE 编程语言排行榜中,两度超越了 C++,涌进排行榜的前三甲。
但当前的 Python 是否真的如此完美?
作者 | Daniel Kats
译者 | 弯月
出品 | CSDN(ID:CSDNnews)
我刚刚从本月早些时候在 PyCon Canada 上演讲的兴奋中平静下来。在会议上我见到了许多聪明的人,似乎每个人都在谈论着同样的痛点和希望。在这篇文章中,我将总结当前最为流行的编程语言 Python 的趋势,以及所面临的现状。
我喜欢 Python,且在个人项目和专业项目上使用 Python 也将近 10 年了。我的工作一半是数据分析,另一半是快速原型创建,所以 Python 是个绝佳的工具。Python 本身最大的优点就是它有大量的库,可以用来干任何事情:机器学习、数据探索、可复现的研究、可视化、云功能、Web API、以及其他所有你能想到的东西。
我离不开 Python 的原因之一就是 Python 的社区非常好,在 StackOverflow 和 GitHub 上与他人交流是一件非常愉快的事情。2015 年,我的一个朋友在我们学校组织 PyCon Canada,拉着我去做志愿者。我发现社区非常友好,也非常有创造力。今年,我觉得我应该做一些回馈,在我的家乡多伦多举行的 PyCon 上做一次演讲。短短三年内社区成长了很多,我对此感到十分震惊。
和以前一样,我发现社区里到处都是聪明又富有创造力的人。一个例子就是在这次演讲中,有一位嘉宾分享了:用 Python 发现哈利波特中的性别偏差”,不管你觉得这个题目如何,但确实是个非常抓人眼球又非常好笑的题目。
但是,像任何工程一样,Python 依然在建设中。我们对于 Python 语言的感受甚至不同于五年前,因此当时一些看似不熟悉的事情,今天不仅成为了可能,甚至成为了理所当然。这篇文章将阐述一些 Python 的发展方向,以及我对于它们成长的看法。
2018 年的 Python 世界中出现了许多新东西,一些甚至度过了成长的烦恼期。下面是我个人喜爱的一些:
JupyterLab
Jupyter Notebook 是一个可以执行 Python(及其他语言)的 Web 应用程序,并能立即以嵌入的方式查看执行结果,包括图表、格式化后的表格以及 Markdown 各式的文字等。它还会自动保存中间结果(像 REPL 一样),可以导出成多种格式,还有上百种其他功能。
Jupyter Notebook 在社区中被广泛使用,特别是在研究和科学领域。Jupyter 团队毫无争议地赢得了 2017 年的 ACM 软件系统奖。
JupyterLab 是在传统 Jupyter notebook 上进行了改进。它包含一些非常好的功能,如单元格拖拽、嵌入式查看数据文件(如 CSV)、标签页式的环境,以及一个以命令为中心的界面。当然它仍然在 beta 阶段,还有一些小问题,如 Revea.js 幻灯片导出功能,单元格折叠功能等都不能正常使用。但整体来说,它表明一个好的工具会不断成长并进步,以满足用户的复杂需求。
mypy
mypy 是一个 Python 的静态类型检查工具,它已经出现有一段时间了。但是,这几年它发展得很好了,你甚至可以把它通过 git hooks 或其他 CI 流程来集成到产品的项目中。我发现它对所有代码都非常有用,甚至能在我编写单元测试之前捕获到我的各种错误。当然它也不是没有陷阱。许多情况下你得写一些看似多余的注释:
__init__(self, *args) -> None
其他行为我也认为有些奇怪。而且,许多常用的模块都没有类型文件,如:
因此这些库会阻碍你将 mypy 集成到你的 CI 系统中,除非你做出大量配置。--ignore-missing-imports 选项基本上是必须的。我希望以后为各种库的模块提供类型文件能成为社区的基本标准。
pipfile 和 pipenv
pipfile 让我感到非常激动!pipfile 是 PEP508 的一个实现,它的动机是用依赖管理系统替换 requirements.txt。
最原始的动机就是,使用 pip 进行的依赖管理与其他 Rust、Javascript 等语言中类似的系统比起来太落后了。虽然 pip / requirements.txt 的缺点众所周知的,但我见过总结得最全面的就是这篇文章(
https://www.kennethreitz.org/essays/a-better-pip-workflow)。我建议阅读一下全文,不过大致内容如下:
requirements.txt 没有标准:它应该列出所有直接和间接的依赖,或者只是直接的依赖?是否应该包括固定的版本号?另外,开发时所需的依赖也非常依赖个人喜好。不同的开发团队会使用不同的规则,会让构建的重现成问题。
为了保证依赖列表最新,就要在 pip install $package 之后立即执行 pip freeze > requirements.txt,这个流程非常难用,而且有许多问题。
依赖管理系统包含三个工具和标准(virtualenv,pip和requirements.txt),它们之间并没有明确的互操作性。它们的存在都是为了完成单一的任务,那么为什么没有单一的工具来做这件事呢?
使用 pipenv 吧。
pipenv 会自动创建 virtualenv,安装并管理该 virtualenv 下的所有依赖,并自动保持 pipfile 最新。
尽管这个想法很好,但使用起来很麻烦。我在实际使用中遇到了许多问题,经常得回到前一种方式,比如显式地使用 virtualenv。我还发现 locking 操作非常慢(部分源自 setup.py 的标准,也是工具链生态标准中的许多问题之一)。
f-strings
f-strings 太棒了!许多人都写过 f-strings 的好处,包括它们自然的语法和带来的性能提升。我没有必要重复这些点,我只想说,这个功能非常棒,从它一出现我就一直在用。
f-strings 带来的一个有点讨厌的地方就是书写 print 语句和 logging 语句之间的区别。logging 模块很好,而且默认情况下,如果日志消息被关闭,那么格式化就不会进行。所以你可以写:
x = 3logging.debug(‘x=%d’, x)
如果日志级别设置为 DEBUG,就会输出 x=3,但如果日志级别更高,就不会进行字符串插值。这是因为 logging.debug 是函数,而字符串作为参数传递。可以在这篇“非常容易理解的 C 源代码”文章(
https://github.com/python/cpython/blob/master/Lib/logging/__init__.py#L1419)中看到它的工作原理。但是,如果这样写,这个功能就消失了:
x = 3logging.debug(f’x={x}’)
不管日志级别是什么,字符串插值必然会执行。从语言层面来看这是合理的,但实际的结果却让人感到不安。调试时我会首先使用 print 语句,如果一切看起来正常,我就会将 print 转成 logging 语句。所以每个 print 语句都需要手动改写,以便匹配不同类型的字符串插值。我不知道应该如何解决这个问题,但我想指出这个问题,因为别人没说过。
像许多与 Python 一样老的项目一样(Python 都和我一样老了),一些模块和思想也上了年纪。这不是吐槽大会,我只是想说 Python 的社区可以做得更好。
tox
Tox 依然是 Python 世界中最好的测试执行器,而且它也非常糟糕。不仅是因为 tox.ini 的语法很不直观,工具本身也非常慢。当然这并不是 tox 自己的错误,而是整个 setup.py 系统就有设计缺陷。因为这些文件定义了包之间的依赖,而它们执行代码查找依赖继承关系就非常慢。这导致一系列工具都很慢。我相信 2019 年我们的社区应该尝试解决这个问题。
此外,它依然不支持 pipfile,让它变得更慢。像许多东西一样,并不是说它本身好坏,而更大程度上取决于它周围工具的好坏。
类型标注只能用于工具
引用自 PEP0484:
使用类型提示进行性能优化作为读者练习。
考虑到该 PEP 出现时 Python 的状态,这一点也是可以理解的,但现在应该更进一步了。我们已经成功地转移到了 Python3,360 个 PyPi 上下载次数最多的包中有 359 个都兼容 Python3。类型提示深受社区欢迎。更进一步,Python 的类型提示应该带来更多好处,如类型优化、自动运行时类型断言等。我发现运行时类型断言非常有用(特别是在函数库中),但手工编写非常麻烦。再加上类型提示,维护多个类型系统就变得特别麻烦。
就像其他提到的那样,Python 4 很可能会把 JIT 当做最优先的功能。似乎这是个给类型标注进行性能优化的好地方。
变量可修改性
对于现在的 Python 我最大的不满就是它没有 const 或类似的东西。在我犯过的所有编码错误中,90% 都是类型相关的错误(现在可以通过 mypy 捕获大部分),或是以为自己创建了新变量,实际上却错误地使用了同一个函数中定义过的变量。我知道有些包能实现这一点,但我希望 Python 自身能支持 const。
nbconvert
nbconvet 项目非常赞。它可以将 Jupyter notebook 转换成其他各种格式,包括 PDF、Reveal.js 幻灯片,或者可执行脚本。在过去几个月内我经常使用后两者,它们真的改变了我的工作流程。我可以把一切都放在一个 notebook 中,最后再将其转换成幻灯片在每周会议上把我的进度演示给同事。类似地我也可以在 notebook 中规划一个想法,然后只需最小的代价将其转换成脚本并用在产品中。
当然这只是想法。现实是,任何大小的 notebook 转换成脚本都需要大量手工操作才能成功转换,有时还不如手动复制粘贴。我听说许多公司创建了 nbconvert 的 wrapper 使它更容易使用。我希望这些人能开源,这样就能解决我的痛苦了。
许多优秀的人鼓励我写这篇文章,我感谢他们的反馈和支持。如果你有不同意见,欢迎留言分享你的看法。
原文:https://medium.com/@
dbkats/state-of-python-in-2018-68fe478f8bb6本文为 CSDN 翻译,如需转载,请注明来源出处。