聊聊Python

原创 2017年09月05日 19:57:36

1.1 Python的现状与未来

Python的历史最早可追溯到20世纪80年代末,但是1.0版的发行时间是在1994年,所以Python并不是一门非常年轻的语言。这里本该介绍Python主要版本发布的整个时间线,但其实真正重要的日期只有一个:2008年12月3日,也就是Python 3.0的发布日期。

在写作本书时,Python 3的首次发布已经过去了7年。PEP 404也已经创建了4年,PEP 404是“取消发布"(un-release)Python 2.8并正式关闭Python 2.x分支的官方文档。虽然过去了这么长的时间,Python 社区中依然存在明显的分歧。语言本身在迅速发展,但大量用户却并不想更新版本。

1.2 Python升级及其原因

原因很简单。Python升级是因为有这样的需求。语言之间的竞争随时都在上演。每隔几个月都会突然冒出一门新语言,声称解决了之前所有语言中存在的问题。对于大多数类似的项目,开发人员很快就会失去兴趣,它们的名气也只是一时炒作。

不管怎样,这也表示存在着更严重的问题。人们之所以设计新的编程语言,是因为他们发现现有的语言无法以最佳方式来解决问题。认识不到这样的需求是目光短浅的。此外,Python的使用范围也越来越广泛,人们发现它有许多可以改进的地方,也应该做出这样的改进。

Python的很多改进往往是由特定应用领域的需求驱动的。其中最重要的领域是Web开发,这一领域需要Python改进对并发的处理。

有些变化只是由于Python项目的历史原因导致的。这些年已经发现了Python的一些不合理之处,有些是标准库模块结构混乱或冗余,有些是程序设计缺陷。最初,发布Python 3是要对这门语言进行较大的清理与更新,但结果显示,这个计划并没有收到预期的效果。在很长一段时间内,很多开发人员对Python 3只是抱着好奇的态度而已,但希望这种情形正在好转。

1.3 追踪Python最新变化——PEP文档

Python社区有一种应对变化的固定方法。虽然各种各样的Python语言修改意见主要在邮件列表(python-ideas@python.org)中进行讨论,但只有发布了名为PEP的新文档,新的变化才会生效。PEP的全称是Python改进提案(Python Enhancement Proposal,PEP)。它是提交Python变化的书面文档,也是社区对这一变化进行讨论的出发点。这些文档的整个目的、格式和工作流程的标准格式也都包含在一份Python改进提案中,也就是PEP 1文档(http://www.python.org/dev/peps/pep-0001)。

PEP文档对Python的作用十分重要,根据讨论的主题,PEP主要有以下3种用途。

  • 通知:汇总Python核心开发者需要的信息,并通知Python发布日程。

  • 标准化:提供代码风格、文档或其他指导意见。

  • 设计:对提交的功能进行说明。

所有提交过的PEP都被汇总在一个文档中,就是PEP 0(https://www.python.org/dev/peps/)。由于这些PEP都在同一个网站上很容易找到,其URL也很容易猜到,因此本书一般用编号来指代这些文档。

如果你对Python语言的未来发展方向感兴趣,但又没时间跟踪Python邮件列表中的讨论,那么PEP 0会是很好的信息来源。它会告诉你,哪些文档已被接受但尚未实施,哪些文档仍在审议中。

PEP还有其他的用途。人们通常会问这样的问题:

  • A功能为什么要以这样的方式运行?

  • Python为什么没有B功能?

大多数情况下,关于该功能的某个PEP文档已经给出了上述问题的详细回答。很多提交的关于Python语言功能的PEP文档并没有通过。这些文档可作为历史资料来参考。

1.4 当前Python 3的普及程度

Python 3有许多强大的新功能,那么它在社区中广泛普及了吗?遗憾的是,并没有。有一个著名的网站叫“Python 3荣耀之墙(Python 3 Wall of Superpowers)”,里面记录了大多数常用软件包与Python 3的兼容性,不久前这个网站刚刚改名为“Python 3耻辱之墙(Python 3 Wall of Shame)”。目前这种状况正在逐步改善,上述网站的软件包列表中绿色的比例也在每月缓慢增加[1]。尽管如此,但这并不代表很快所有应用开发团队都只使用Python 3。当所有常用软件包都支持Python 3时,“我们所用的软件包还没有迁移到Python 3”这一常用借口将不再适用。

造成目前这种状况的主要原因是,将现有应用从Python 2迁移到Python 3上总是一项不小的挑战。像2to3之类的工具可以进行代码自动转换,但无法保证转换后的代码100%正确。而且,如果不做人工修改的话,转换后的代码性能可能不如转换前。将现有的复杂代码库迁移到Python 3上可能需要付出巨大的精力和成本,某些公司可能无法负担这些成本。但这些成本可以分割成小份来逐步完成。一些优秀的软件架构设计方法可以帮助其逐步实现这一目标,如面向服务的架构或者微服务。新的项目组件(服务或微服务)可以用新方法编写,现有的项目组件可以逐步迁移。

长远来看,将项目迁移到Python 3只有好处。根据PEP-404这份文档,Python 2.x分支将不会发布2.8版本。而且未来所有重要的项目(如Django、Flask和NumPy)可能都将放弃2.x的兼容性,仅支持Python 3。

我个人对这个问题的观点可能会引发争议。我认为在创建新的软件包时,最好鼓励社区完全放弃支持Python 2。当然,这一做法极大地限制了这些软件的适用范围,但对于那些坚持使用Python 2.x的人来说,这可能是改变他们想法的唯一方法。

1.5 Python 3和Python 2的主要差异

前面已经说过,Python 3打破了对Python 2的向后兼容。但它并不是完全重新设计的。而且,也并不是说2.x版本的Python模块在Python 3下都无法运行。代码可以完全跨版本兼容,无需其他工具或技术在两大版本上都可以运行,但一般只有简单应用才能做到这一点。

1.5.1 为什么要关注这些差异

本章前面说过我个人对Python 2兼容性的看法,但是目前不可能完全忽视这一点。还有一些Python包(例如第6章将讲到的fabric)十分实用,但可能短期内不会迁移到Python 3。

另外,有时我们还会受到所在公司的制约。现有的遗留代码可能非常复杂,迁移代码的费用难以承受。所以即使我们现在决定只用Python 3,短期内也不可能完全放弃Python 2。

如今想要自称专业开发者,没有对社区的回馈是说不过去的,所以帮助开源软件开发者向现有软件包中添加对Python 3的兼容,可以很好地偿还在使用这些软件包时产生的“道德债(moral debt)”。当然,不了解Python 2和Python 3的差异是无法做到这一点的。顺便提一下,对于Python 3新手来说,这也是一项很好的练习。

1.5.2 主要的语法差异和常见陷阱

要比较不同版本之间的差异,最好的参考资料就是Python文档。不过为了方便读者,本节总结了其中最重要的内容。但不熟悉Python 3的读者还是要去阅读官方文档。

Python 3引入的重要差异一般可分为以下几个方面。

  • 语法变化,删除/修改了一些语法元素,并添加了一些新的语法元素。

  • 标准库中的变化。

  • 数据类型与集合的变化。

1.语法变化

有些语法变化会导致当前代码无法运行,这些变化是最容易发现的,它们会导致代码根本无法运行。包含新语法元素的Python 3代码在Python 2中无法运行,反之亦然。由于删除了某些元素,导致Python 2代码显然无法与Python 3兼容。运行有这些问题的代码时,解释器很快就会抛出SyntaxError异常。下面是一个无法运行的脚本示例,只包含两个语句,都会引发语法错误而无法运行:

 print("hello world") print "goodbye python2"

上述代码在Python 3中的实际运行结果如下:

$ python3 script.py File "script.py", line 2 print "goodbye python2" ^SyntaxError: Missing parentheses in call to 'print'

列出所有的语法差异会比较长,而且Python 3.x的新版本也会不时添加新的语法元素,在较早版本的Python中就会引发错误(即使在相同的3.x版本上也会报错)。其中最重要的语法差异将会在第2章和第3章中讲到,所以这里无需全部列出。

与Python 2.7相比,删除或改动的内容要相对少一些,下面给出最重要的变化内容。

  • print不再是一条语句而是一个函数,所以必须加上括号。

  • 捕获异常的语法由except exc, var改为except exc as var

  • 弃用比较运算符<>,改用!=

  • from module import https://docs.python.org/3.0/reference/simple_stmts.html#import)现在只能用于模块,不能用在函数中。

  • 现在from .[module] import name是相对导入的唯一正确的语法。所有不以点字符开头的导入都被当作绝对导入。

  • sorted函数与列表的sort方法不再接受cmp参数,应该用key参数来代替。

  • 整数除法表达式(如1/2)返回的是浮点数。取整运算可以用//运算符,如1//2。这样做的好处是浮点数也可以用这个运算符,所以5.0//2.0 == 2.0

2.标准库中的变化

语法变化很容易发现,标准库中的重大变化也是非常容易发现的。Python的每个后续版本都会向标准库模块中添加、弃用、改进或完全删除某些内容。在旧版Python(1.x和2.x)中也会定期有这样的变化,所以出现在Python 3中并不让人吃惊。大多数情况下,对于删除或重组的模块(例如urlparse移到了urllib.parse),在运行解释器时会对导入语句抛出异常。这样的问题很容易发现。无论如何,为了确保能够发现所有类似的问题,完整的代码测试覆盖率是必不可少的。在某些情况下(例如使用延迟加载模块时),这个通常在全局导入时出现的问题并不会出现,直到在代码中将某些模块作为函数调用时才会出现。因此,在测试期间确保每行代码都要实际运行是很重要的。

技巧.tif 

延迟加载模块

延迟加载模块是指在全局导入时并不加载的模块。在Python中,import语句可以包含在函数内部,这样导入是在函数调用时才会发生,而不是在全局导入时发生。在某些情况下,模块的这种加载方式可能比较合理,但大多数情况下,这只是对设计不佳的模块结构的变通方法(例如避免循环导入),通常应避免这种加载方式。当然,对于标准库模块来说,没有理由使用延迟加载。

3.数据类型与集合的变化

开发人员在努力保持兼容性或只是将现有代码迁移到Python 3上时,需要特别注意Python中数据类型与集合的表示方式的变化。虽然不兼容的语法变化或标准库变化很容易发现,也很容易修复,但集合与数据类型的变化要么难以察觉,要么需要大量的重复工作。这样的变化列表会很长,再次重申,官方文档是最好的参考资料。

不过,这一节必须讲一下Python 3中字符串处理方式的变化,因为这是Python 3中最具争议也是讨论最多的变化,尽管这是一件好事,使很多问题变得更加明确。

现在所有字符串都是Unicode,字节(bytes)需要加一个bB的前缀。Python 3.0和3.1不支持使用u前缀(例如u"foo"),使用的话会引发语法错误。不支持这个前缀是引发所有争议的主要原因。这导致难以编写能够兼容Python不同分支的代码,2.x版需要用这个前缀来创建Unicode。Python 3.3又恢复了这个前缀,虽然没有任何语法上的意义,只是为了简化兼容过程。

1.5.3 用于保持跨版本兼容性的常用工具和技术

在Python不同版本之间保持兼容性是一项挑战。根据项目的大小不同,这项挑战可能会增加许多额外的工作量,但绝对可行,也很值得去做。对于在许多环境中都会用到的Python包来说,必须要保持跨版本兼容性。如果开源包没有定义明确并经过测试的兼容范围(compatibility bound),是不太可能流行起来的。而且,对于只在公司网络封闭使用的第三方代码来说,也可以大大受益于在不同环境中的测试。

这里应该注意,虽然这一部分内容主要关注Python不同版本之间的兼容,但这些方法也适用于保持与外部依赖项之间的兼容,外部依赖项包括不同的包版本、二进制库、系统或外部服务等。

整个过程主要分为3个部分,按重要性排序如下。

  • 定义并记录目标兼容范围的及其管理方法。

  • 在每个环境中进行测试,并对每个兼容的依赖版本进行测试。

  • 实现实际的兼容代码。

告知兼容范围是整个过程中最重要的一部分,因为这可以让代码使用者(开发人员)对代码的工作原理和未来的变化方式有一定的预期和假设。我们的代码可能用于多个不同项目的依赖,这些项目也在努力管理兼容性,所以把代码兼容性说清楚还是很重要的。

本书总是尽量给出几个选择,而不会强烈推荐某个特定选项,而这里是少数几个例外之一。目前来看,管理兼容性未来变化的最佳方法,就是正确使用语义化版本(Semantic Versioning semver)的版本号。它是一个广为接受的标准,用仅包含3个数字的版本标识符来标记代码的变化范围。它还给出了如何处理弃用的方法建议。下面是摘录semver官网的摘要。

版本格式:主版本号.次版本号.修订号,版本号递增规则如下。

  • 主版本号(MAJOR):当你做了不兼容的API修改。

  • 次版本号(MINOR):当你做了向后兼容的功能性新增。

  • 修订号(PATCH):当你做了向后兼容的问题修正。

先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

测试时就会发现一个悲伤的事实,为了保证代码与每个依赖版本和每个环境(这里环境指的是Python版本)都保持兼容,必须在所有可能的组合中对代码进行测试。当然,如果项目的依赖很多,做到这一点基本是不可能的,因为随着依赖版本数目的增加,组合的数目也会迅速增加。因此,通常需要做一些权衡,使得运行所有兼容性测试无需花费数年的时间。第10章中介绍一般的测试,里面也介绍了所谓的矩阵测试中工具的选择。

提示.tif  

项目遵循semver的好处在于,通常只有主版本才需要测试,因为次版本和修订版本中保证没有向后不兼容的变化。只有项目不违背这样的约定,这种说法才能成立。不幸的是,每个人都会犯错,许多项目中都出现了后向不兼容的变化,甚至在修订版本中也出现了这种变化。尽管如此,由于semver声称对次版本和修订版本的变化保持严格的向后兼容,那么打破这个规则就可以视为bug,可以在修订版本中进行修复。

如果明确定义了兼容范围并严格测试,那么实现兼容层就是最后一步,也是最不重要的一步。但是,每一位对这个话题感兴趣的程序员都应该知道下列工具和技术。

最基本的就是Python的future模块。它将Python新版本中的一些功能反向迁移到旧版本中,采用的是导入语句的形式:

 from future import <feature>

future语句提供的功能是和语法相关的元素,其他方法很难处理这些元素。这个语句只能影响它所在的模块。下面是Python 2.7交互式会话的实例,从Python 3.0中引入Unicode:

Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit(Intel)] on win32Type "help", "copyright", "credits" or "license" for moreinformation.>>> type("foo") # 旧的字面值<type 'str'>>>> from future import unicode_literals>>> type("foo") # 现在变成了unicode<type 'unicode'>

下面列出了所有可用的future语句,关注2/3兼容性的开发者都应该知道。

  • division:Python 3新增的除法运算符(PEP 238)。

  • absolute_import:将所有不以点字符开头的import语句格式解释为绝对导入(PEP 328)。

  • print_function:将print语句变为函数调用,所以在print后面必须加括号(PEP 3112)。

  • unicode_literals:将每个字符串解释为Unicode(PEP 3112)。

future中的可选语句列表很短,只包含几个语法功能。对于其他变化的内容,例如元类语法(第3章会讲到这一高级特性),维持其兼容性则困难得多。future语句也无法完全解决多个标准库重组的问题。幸运的是,有些工具旨在提供一致可用的兼容层。最有名的就是Six模块,提供了常用的2/3兼容性的整个样板。另一个很有前途但名气稍逊的工具是future模块。

在某些情况下,开发人员可能不想在一些小型Python包里添加其他依赖项。通常的做法是将所有兼容性代码放在一个附加模块中,该模块通常命名为compat.py。下面是来自python-gmaps项目的compat模块实例:

 # -- coding: utf-8 -*- import sys if sys.version_info < (3, 0, 0): import urlparse # noqa def is_string(s): return isinstance(s, basestring) else: from urllib import parse as urlparse # noqa def is_string(s): return isinstance(s, str)

这样的compat.py模块十分常见,即使是利用Six保持2/3兼容性的项目也很常见,因为这种方法非常方便,用于保存在不同版本的依赖包之间保持兼容性的代码。

技巧.tif 

下载示例代码

你可以用自己的账号在Packt的官方网站下载本书的示例代码文件。如果你是在其他地方购买的本书,你可以访问Packt的官方网站并注册,文件会直接通过邮件发送给你。

下载代码文件的步骤如下。

  • 用你的电子邮件地址和密码登录或注册我们的网站。

  • 将鼠标指针悬停在顶部的SUPPORT选项卡上。

  • 单击Code Downloads & Errata

  • Search框中输入本书的名字。

  • 选择你要下载代码文件的书籍。

  • 从下拉菜单中选择本书的购买途径。

  • 单击Code Download

文件下载完成后,请确保用下列软件的最新版本对文件夹进行解压或提取。

  • 在Windows上用WinRAR或7-Zip。

  • 在Mac上用Zipeg、iZip或UnRarX。

  • 在Linux上用7-Zip或PeaZip。

本书的代码包也托管在GitHub,网址为https://github.com/ PacktPublishing/Expert-Python-Programming_Second- Edition。在GitHub上还有大量图书和视频资源。去看一下吧!


1.6Python从入门到放弃


Python大全都在这儿了 ,要不要放弃随你哦~~


Python高级编程(第2版)    

Python高级编程(第2版)        

  精通Python自然语言处理    

精通Python自然语言处理


    Python设计模式(第2版)    

Python设计模式(第2版)        


     Python金融实战    

Python金融实战        


     Python高性能编程    

Python高性能编程 


       NLTK基础教程——用NLTK和Python库构建机器学习应用    

NLTK基础教程——用NLTK和Python库构建机器学习应用


       Python极客项目编程    

Python极客项目编程


     Python机器学习实践指南    

Python机器学习实践指南


     Python地理数据处理    

Python地理数据处理


       Python地理空间分析指南(第2版)    

Python地理空间分析指南(第2版


    Python机器学习——预测分析核心算法    

Python机器学习——预测分析核心算法


  基于ArcGIS的Python编程秘笈(第2版)    

基于ArcGIS的Python编程秘笈(第2版)


  Python数据科学指南    

Python数据科学指南 


 Python高手之路(第3版)    

Python高手之路(第3版)


     Python参考手册(第4版•修订版)    

Python参考手册(第4版•修订版


    用Python写网络爬虫    

用Python写网络爬虫


     Python游戏编程快速上手    

Python游戏编程快速上手

       Python Cookbook(第3版)中文版    

Python Cookbook(第3版)中文版 


     Python数据可视化编程实战    

Python数据可视化编程实战 


      Python高手之路    

Python高手之路


     贝叶斯思维:统计建模的Python学习法    

贝叶斯思维:统计建模的Python学习法 


     趣学Python——教孩子学编程    

趣学Python——教孩子学编程

       Python游戏编程入门    

Python游戏编程入门


      Python 3程序开发指南(第2版•修订版)    

Python 3程序开发指南(第2版•修订版

       “笨办法”学Python(第3版)    

“笨办法”学Python(第3版

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

python for data analysis 2nd

python学习之路-基础篇-day04

大纲: 1.装饰器 2.迭代器 3.生成器 4.json和pickle的序列化和反序列化 一.装饰器decorator 1.什么是装饰器? 装饰器的本质就是返回函数的高阶函数,用来装饰其...

Python_7

1. scoundrel={'name':'Grubby','girlfirend':'Mary'} key,value=scoundrel.popitem() print key print va...

python窗口置顶

李航《统计学习方法》第十章——用Python实现隐马尔科夫模型

相关文章: 李航《统计学习方法》第二章——用Python实现感知器模型(MNIST数据集) 李航《统计学习方法》第三章——用Python实现KNN算法(MNIST数据集) 李航...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)