Python

Python

Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/),是一种广泛使用的解释型、高级和通用的编程语言。Python支持多种编程范型,包括函数式、指令式、反射式、结构化和面向对象编程。它拥有动态类型系统和垃圾回收功能,能够自动管理内存使用,并且其本身拥有一个巨大而广泛的标准库。它的语言结构以及面向对象的方法,旨在帮助程序员为小型的和大型的项目编写清晰的、合乎逻辑的代码。

吉多·范罗苏姆于1980年代后期开始研发Python,作为ABC语言的后继者,它也可以被视为采用了叫做M-表达式的中缀表示法的一种LISP方言。吉多·范罗苏姆于1991年首次发布 Python 0.9.0。Python 2.0于2000 年发布并引入了新功能。Python 3.0于2008年发布,它是该语言的主要修订版,并非完全向后兼容。Python 2于2020年随2.7.18版停止支持。

Python的设计哲学,强调代码的可读性和简洁的语法,尤其是使用空格缩进来划分代码块。相比于C或Java,Python让开发者能够用更少的代码表达想法。

Python解释器本身几乎可以在所有的操作系统中运行,它的官方解释器CPython是用C语言编写的。Python是一个由社群驱动的自由软件,目前由Python软件基金会管理。Python是最受欢迎的编程语言之一。

历史

Python的创始人吉多·范罗苏姆,在1982年至1995年间,参与了荷兰数学和计算机科学研究学会多个项目的工作。1989年的圣诞节期间,他决心开发一个新的脚本解释编程,作为ABC语言的继承者,并且用它替代Unix shell和C语言来进行系统管理,担负与Amoeba操作系统之间的交互操作并进行异常处理。他是BBC电视剧《Monty Python的飞行马戏团》的爱好者,所以选取了Python作为这个编程语言的名字。范罗苏姆作为Python的主要开发者,独自担负这个项目的发展决策者职责,直到2018年7月12日,他宣布从终身仁慈独裁者(BDFL)的职权上“永久休假”。他在2019年1月至11月参与了第一届五人掌控委员会继续领导项目发展。

在1991年2月,范罗苏姆在alt.sources上发布了最初代码(标记为版本0.9.0),这时就已经存在了带继承的类、异常处理、函数和核心数据类型listdictstr等。在这个最初发行中就有了从Modula-3引进的模块系统,它的异常模型也类似于Modula-3。在1994年1月Python达到了版本1.0。这个发行版主要新特征是包括了由Amrit Prem提供的函数式编程工具lambdamapfilterreduce。Python 1.4增加了受Modula-3启发的关键字参数,和对复数的内建支持,还包含了采取名字修饰的一种基本形式的数据隐藏。

Python 2.0于2000年10月16日发布,介入了列表推导式,这是从函数式编程语言SETL和Haskell中引入的。它还向垃圾收集系统增加了环检测算法,并且支持Unicode。Python 2.1支持了嵌套作用域,就像其他静态作用域语言一样。Python 2.2的重大革新是将Python的类型(用C写成)和类(用Python写成)统一入一个层级,使得Python的对象模型成为纯粹和一致的面向对象的模型;还增加了迭代器,受CLU和Icon启发的生成器,和描述器协议。Python 2.4加入了集合数据类型,和函数修饰器。Python 2.5加入了with语句。

Python 3.0于2008年12月3日发布,它对语言做了较大修订而不能完全后向兼容。Python 3发行包括了2to3实用工具,它(至少部分的)自动将Python 2代码转换成Python 3代码。Python 3的很多新特性后来也被移植到旧的Python 2.6/2.7版本中。

Python 2.7的产品寿命结束日期最初设定为2015年,出于对大量的现存代码不能前向移植到Python 3的关切,而将对它的支持延期至2020年。随着Python 2的产品寿命结束,2022年3月14日发布的macOS 12.3已经彻底移除了Python 2。当前只有Python 3的稳定版本3.10、3.11和预览版本3.12正在被完全支持,但仍提供对3.7、3.8和3.9版本的安全性修正。

在2021年12月,活跃的Python核心开发者选举Pablo Galindo Salgado、Petr Viktorin、Thomas Wouters、Gregory P. Smith和Brett Cannon为2022年度“掌控委员会”的五位成员来领导这个项目。

特征与设计哲学

Python是多范型编程语言。它完全支持结构化编程和面向对象编程,还有很多特征支持函数式编程和元编程比如元对象协议(元类和魔术方法)。通过扩展还可以支持很多范型,包括面向切面编程、契约式设计和逻辑编程。

Python使用动态类型,在内存管理上采用引用计数和环检测相结合的垃圾收集器。它的特征还有动态名字解析(后期绑定),即在程序执行期间绑定方法和变量的名字。

Python对遵循LISP传统的函数式编程提供了有限的支持,它提供了 mapfilterreduce函数;列表推导式、字典、集合和生成器表达式。标准库中的模块functoolsitertools,实现了从Haskell和Standard ML借鉴来的函数式工具。

Python的设计理念是“优雅”、“明确”、“简单”,它的一些重要准被合称为“Python之禅”。在Python解释器内运行import this可以获得完整的列表,下面举出其中首要:

  • 优美优于丑陋。明了优于隐晦。
  • 简单优于复杂。复杂优于凌乱。
  • 扁平优于嵌套。稀疏优于稠密。
  • 可读性很重要。

Python开发者的方法论是“用一种方法,最好是只有一种方法来做一件事”,显著不同于以Perl语言为代表的“不止一种方法去做一件事”风格。Python开发者在设计语言时,如果面临多种选择,一般会拒绝花俏的语法,而选择明确没有或者很少有歧义的语法。

范罗苏姆认为ABC语言非常优美和强大,它没有获取成功的原因是不开放造成的,故而将Python本身设计为可扩展的。Python并不把所有的特性和功能都集成到语言核心,而是提供了丰富的API和工具,以便程序员能够轻松地使用Python、C、Cython来编写扩展模块。Python还可以通过外界函数接口如标准库中的ctypes等,来访问动态链接库或共享库中C兼容数据类型并调用其中函数,以便于对用其他语言编写的编程进行集成和封装。

Python开发人员尽量避开不成熟或者不重要的优化。一些针对非重要部位的加快运行速度的补丁,通常不会被合并到Python的官方实现CPython中。在某些对运行速度要求很高的情况,可以使用JIT技术的Python实现或扩展。

语法

Python的设计目标之一是让代码具备高度的可阅读性。它设计时尽量使用其它语言经常使用的标点符号和英文单字,让代码看起来整洁美观。Python语句之后的分号是可选的,作为动态语言不需要书写“声明”语句,不同于其他的静态语言如C、Pascal。

缩进

Python语言利用缩进表示语句块的开始和结束(越位规则),而非使用大括号或者某种关键字。增加缩进表示语句块的开始,而减少缩进则表示语句块的结束。根据PEP 8的规定,使用4个空格来表示每级缩进。

使用Tab字符和其它数目的空格虽然都可以被解释器识别,但不符合编码规范,偏向使用Tab字符的程序员可以设置文本编辑器将Tab键转换为4个空格。缩进成为了语法的一部分,并且Python开发者有意让违反了“缩进规则”的程序不能通过解释。

关键字

Python有如下35个关键字或“保留字”;它们不能用作标识符:

  • and
  • as
  • assert
  • async
  • await
  • break
  • class
  • continue
  • def
  • del
  • elif
  • else
  • except
  • False
  • finally
  • for
  • from
  • global
  • if
  • import
  • in
  • is
  • lambda
  • None
  • nonlocal
  • not
  • or
  • pass
  • raise
  • return
  • True
  • try
  • while
  • with
  • yield

注释

  1. ^ 1.0 1.1 从Python 3.5开始,介入了asyncawait
  2. ^ 2.0 2.1 2.2 从Python 3开始,介入了关键字TrueFalsenonlocal

标识符

标识符就是名字,在ASCII范围内(U+0001..U+007F),可用于标识符的字符为:大写字母AZ和小写字母az,下划线_以及数字09,但首字不可以用数字。有如下命名约定:

  • _spam(单下划线开头):弱“内部使用”标识。对于from M import *,将不导入所有以下划线开头的对象。
  • spam_(单下划线结尾):为了避免与python关键字的命名冲突。
  • __spam(双下划线开头):在命名一个类特性的时候,采用名字修饰,比如在类SpamEggs内,__spam将变成_SpamEggs__spam
  • __spam__(双下划线开头双下划线结尾):指那些包含在用户控制的名字空间中的“魔术”方法或特性,比如__name____doc____init____import____file__等。建议永远不要将这样的命名方式应用于自己的变量或函数。

在Python文献中经常使用的元语法变量是spam和eggs而非传统的foo和bar。

语句和控制流

Python的语句包括:

  • 赋值语句,记号为等号=。Python支持并行赋值,可以同时给多个变量赋值,还可以交换两个变量的值。
  • del语句,递归的进行删除。
  • pass语句,充当NOP,表示此行为空,不执行任何操作。
  • assert语句,用于编程调适阶段时测试执行条件是否满足。
  • if语句,当条件成立时执行语句块。经常与elifelse配合使用。
  • for语句,遍历列表、字符串、字典、集合等迭代器,依次处理迭代器中的每个元素。
  • while语句,当条件为真时,循环执行语句块。
  • break语句,从循环中跳出。
  • continue语句,越过这次迭代并继续进行下个项目。
  • try语句,与exceptelsefinally配合使用,处理在编程执行中出现的异常情况。
  • raise语句,抛出一个异常。
  • class语句,用于定义类,它执行一块代码并将它的局部名字空间附属至一个类。
  • def语句,用于定义函数和方法。
  • return语句,用来从函数返回值。
  • yield语句,使用它从一个生成器中返回一个值。在版本2.5之前,生成器是惰性迭代器,信息是单向的从生成器传递出来的。自从版本2.5,yield也是一个有返回值的运算符,能够将信息传递回到生成器函数中。自从版本3.3,信息可以传递通过多个堆栈层级。
  • with语句,把一块代码包裹在一个上下文管理器之内。例如,在一块代码执行之前获取一个锁并且在此后释放这个锁,或打开一个文件并且在此后关闭它。它允许了资源获取即初始化(RAII)式行为并可替代常见的try/finally惯用法。
  • import语句,导入一个模块或包。有三种用法:import <模块名字> [as <别名>]from <模块名字> import *from <模块名字> import <定义1> [as <别名1>], <定义2> [as <别名2>], ...

在Python中赋值语句所进行的操作是将一个名字绑定为到一个分立的、动态分配的对象的一个引用。因为名字的存储位置不“包含”这个指示的值,称它为“变量”是不准确的。这个名字可以随后在任何时候重新绑定到极大不同的各种类型的对象上,包括字符串、过程、具有数据和方法的复杂对象等等。因为名字是通用的引用持有者,给它关联一个固定的数据类型是不合理的。但是在给定时间一个名字总是被绑定到有一个类型的某个对象上,因此这是动态类型。接连的把一个共同的值赋值给多个名字,比如x = 2; y = 2; z = 2,导致给3个名字和1个数对象分配存储,这3个名字都绑定到这1个数对象上。Python赋值语句的这种基础机制,不同于传统指令式编程语言比如C中的赋值,在这里右手侧的值被复制到给这个变量分配的存储位置之中,等号左手侧的变量名字是其符号地址,对为它声明的类型而言分配给它的内存是足够大的。

Python支持并广泛使用异常处理作为检测错误状况和程序中其他“异常”事件的方式。Python风格提倡在可能出现错误状况的任何时候都使用异常。在Python中习惯上不在使用之前对访问一个文件或资源进行测试,而是先行尝试使用它,再捕获访问被拒绝引发的异常。 经常为此援引的格言是葛丽丝·霍普贡献的EAFP:“请求原谅比许可更容易”。Python使用with语句处理资源,在进入一个作用域的时候调用一个函数而在离开它的时候调用另一个函数。这能防止忘记移除资源并且还可处理更复杂的状况比如异常。

Python官方实现不提供尾调用优化或头等续体,吉多·范罗苏姆曾声称永远都不会加以支持,目前只有第三方库支持。Python在版本2.5中通过扩展生成器,提供了对协程式功能的更好支持。版本3.4介入了综合性的异步I/O框架标准化,在其中扩展了利用子生成器委托的协程,这个扩展自从Python 3.8被弃用。Python 3.5通过async/await语法介入了对协程的显式支持。从版本3.7开始async/await成为保留关键字。

模块是定义可以被导入并重用于其他Python程序中的函数和类的Python正规.py文件。import语句找到一个模块,装载它,如果有需要的话初始化它,并且定义用来引用这个模块中代码的一个名字或一些名字。from...import语句,找到、装载、必需时初始化一个模块,接着增加模块引用到局部名字空间,允许访问其中的函数和类而不采用模块引用。from ... import支持*选项来导入所有引用而非指名的特定函数或类。当模块被导入的时候,__name__变量被设置成这个模块的名字。在Python解释器直接运行一个模块的时候,__name__变量被设置为"__main__"。这允许被设计用于导入的模块增加只在模块被直接运行时候执行的代码。dir()函数返回在当前局部作用域中或参数指定的对象中的名字的列表。

表达式

Python中很多表达式与C和java类似,而另一些则与之不同。

  • 在Python中,算术运算的加法+、减法-、乘法*和取模%是与C和java相同的,但是除法的行为不同。在Python中有两种除法,它们是下取整除法(或整数除法)//和浮点除法/ 。Python增加了指数算符**。Python有如下必须用于整数的位运算:&与(AND),|或(OR),~非(NOT),^异或(XOR),>>右移, <<左移。自从Python 3.5,介入了新的@中缀矩阵乘法算符,它已经用于了NumPy库。
  • 在Python中,有如下比较运算:大于>,小于<,等于==,不等于!=,小于等于<=,大于等于 >===按值比较,对比于Java,它按值比较数而按引用比较对象(在Java中比较对象的值可以采用equals()方法)。Python的isis not算符可以用来比较对象的同一性(按引用比较),也就是比较两个变量是否引用了同一个对象。而innot in用于判断一个对象是否属于另外一个对象。在Python中,比较是可以链接起来的,比如a <= b <= c
  • Python使用andornot表示逻辑运算与、或、非,不采用Java和C中所用的符号&&||!
  • 自从Python 3.8,介入了“赋值表达式”语法:=。它也叫做“命名表达式”或“海象”,它将一个表达式赋值给一个标识符,同时还返回这个表达式的值,常用作更大的表达式的一部分。
  • 自从Python 3.9,介入了字典归并算符|和更新算符|=
  • Python支持列表推导式。Python 2.4将列表推导式扩展至更一般性的生成器表达式。Python 3.0和2.7又补全了字典推导式和集合推导式。
  • Python的匿名函数实现为lambda表达式。匿名函数体只能是一个表达式。
  • Python的条件表达式表示为x if c else y。意思是当c为真时,表达式的值为x,否则表达式的值为y。 在运算数的次序上不同于很多其他语言中常见的c ? x : y
  • Python区分列表(list)和元组(tuple)两种类型。列表的写法是[1,2,3],而元组的写法是(1,2,3)。在没有歧义的情况下,元组的圆括号是可选的,一个元素的元组向这个元素尾随一个逗号例如(1,)。列表是可变的,并且不能用作字典的键(Python中字典的键必须是不可变的)。元组是不可变的,因而可以用作字典的键,假定这个元组的所有元素都是不可变的话。可以使用+算符来串接二个元组,这不会直接修改它们的内容,而是产生包含给定元组二者的元素的一个新元组。因此,给定变量t初始时等于(1, 2, 3),执行t = t + (4, 5)时,首先求值t + (4, 5),它产生(1, 2, 3, 4, 5),接着赋值回到t,这在效果上“修改了”t的内容,尽管这还是遵守了元组对象的不可变本性。
  • Python有“序列解包”特征,多个表达式,其中每个都可求值成能被赋值的东西(变量、可写的属性等),以与形成元组文字(literal)相同的方式,关联起来作为一个整体,放置在赋值语句等号的左手侧。这个语句预期在等号的右手侧有一个“可迭代”对象,在迭代它的时候产生同左手侧给出的可写表达式相同数目的值,这个语句对它进行迭代并把每个产生的值赋值给左手侧对应的表达式。这个特征允许从一个单一函数返回多个值。自从Python 3.5,增加了在表达式列表中的“可迭代解包”*和在字典显示中的“字典解包”**
  • Python拥有“字符串格式”算符%。这个功能类同于C中的printf格式化字符串,比如"spam=%s eggs=%d" % ("blah", 2)求值成"spam=blah eggs=2"。在Python 3和2.6+中,这通过str类的format()方法来提供,比如"spam={0} eggs={1}".format("blah", 2)。Python 3.6增加了“f-字符串”:blah = "blah"; eggs = 2; f'spam={blah} eggs={eggs}'
  • Python拥有各种字符串文字:
    • 由单引号'或双引号"界定的字符串。不同于Unix shell、Perl和受Perl影响的语言,单引号和双引号功能相同。这二种字符串都使用反斜杠\作为转义字符。在Python 3.6中字符串插值可作为“格式化字符串”而获得到。
    • 三引号字符串,开始和结束于三个单引号或双引号的序列。它们可以跨越多行,其功能就像shell、Perl和Ruby中的here文档。
    • 原始字符串变体,用给字符串文字前导一个r来指示。转义序列不被解释,因此在文字反斜杠常见的地方很有用,比如正则表达式和Windows风格的路径。可比较于C#中的“@-引用”。
  • Python允许连续出现和只用空白分隔(包括换行)的字符串文字(可能使用了不同的引用约定),它们被聚合成一个单一的更长的字符串。
  • Python拥有在列表上的数组索引和数组分片表达式,表示为a[key]a[start:stop]a[start:stop:step]。索引是基于零的,负数是相对于结尾的。分片从“开始”(start)索引直到但不包括“停止”(stop)索引。分片的第三个参数叫做“步长”(step)或“间隔”(stride),允许元素被跳过和用负数指示反向。分片索引可以省略,例如a[:],这返回整个列表的一个复本。分片的每个元素都是浅层复制的。

在Python中,在表达式和语句之间的区别是严格强制性的,对比于语言如Common Lisp、Scheme或Ruby。这导致重复了某些功能。比如:列表推导式对当for循环。条件表达式对当if块。eval()对当exec()内建函数(在Python 2中,exec是语句);前者用于表达式,后者用于语句。

语句不能成为表达式的一部分,所以列表和其他推导式或lambda表达式,都是表达式,不能包含语句。这个限制的一个特定情况是赋值语句比如a = 1,不能形成条件语句的条件表达式的一部分。这能够避免一个经典的C错误,即在条件中把等于算符==误写为赋值算符=if (c = 1) { ... }在语法上是有效(但可能非预期)的C代码,而if c = 1: ...在Python中导致一个语法错误。

函数

Python的函数支持递归和闭包及其他头等函数特征,但不支持函数重载。Python的函数作为头等对象,具有和普通对象平等的地位。Python的函数实际参数与形式参数之间的结合是传递“对象的引用”,就是把形式参数名字绑定到实际参数名字所引用的对象上。如果形式参数绑定到一个可变的对象,则通过形式参数对此对象内容的修改,在函数外也是可见的。如果形式参数绑定到一个不可变的对象,则通过形式参数是不能修改此对象内容,但可以把形式参数重新绑定到其它对象上,这并不影响函数外的对象的值。

Python的变量有函数作用域、模块作用域和全局作用域。简单访问(不赋值)一个变量的时候,名字解析服从窄到宽的LEGB(局部、包围、全局、内建)顺位规则。在函数中赋值一个变量将导致它成为这个函数的局部变量,就是说它的作用域在整个函数中,而不是在这个赋值之后至这个函数结束,因此在这个赋值之前引用它,不再于这个函数之外查找同名变量而是引发一个错误。缺省的名字解析规则可以用globalnonlocal关键字来覆盖。global声明的变量是全局变量。 global可以用于嵌套的函数中。嵌套函数中还可以使用nonlocal声明,用于赋值到给非局部变量。

Python可以指定形式参数的缺省值,在函数定义时于形式参数序列中以param=value样式进行一次性初始化。形式参数在初始化之后保持既有绑定,函数的后续调用可继续对它进行访问或变更。在函数调用时为有缺省值的形式参数提供实际参数是可选的。Python支持位置实际参数和关键字实际参数。函数调用时,实际参数可以如同C语言那样按照位置与形式参数匹配;也可以采用命名参数(或称为关键字实际参数),即kwarg=value样式的实际参数。使用不对应实际参数的特殊形式参数/*,可以将参数序列分为唯位置参数、可位置可关键字参数和唯关键字参数三部分。有缺省值的形式参数之后不能跟随无缺省值的可位置形式参数。在一个函数调用的实际参数序列中,关键字实际参数必须出现在位置实际参数之后。

在位置和关键字形式参数序列末尾可以分别有*args**kwargs这样的形式参数,它们对应于在函数调用时提供的,超出形式参数序列规定而无所对应的多个实际参数;在形式参数名字前加一个*号,该形式参数argstuple类型,对应可变量目的位置实际参数;在形式参数名字前加**号,该形式参数kwargsdict类型,对应可变量目的关键字实际参数。在位置实际参数已经在一个序列类型如列表或元组的对象中的情况下,在引用它的变量前加一个*号传递给函数,则其中所有元素解包为多个位置实际参数,关键字实际参数在字典中则加**号来传递给函数。

修饰器(decorator)是用来修改一个函数、方法或类定义的任何可调用Python对象。将正被定义的最初对象传递给修饰器,它返回一个修改后的对象,接着把它绑定到在定义中那个名字。Python修饰器部分受到Java注解的影响,而有类似的语法;修饰器语法是纯粹的语法糖,使用@作为关键字形成修饰符。修饰器是一种形式的元编程,它们增强它们所修饰的函数或方法的行动。 多个修饰器可以链接起来,通过在毗连的行上放置多个修饰符,或者使用中间变量。 函数修饰器的正规用法包括:用来创建类方法或静态方法,实现多方法,增加函数特性,跟踪,设置先决条件和后置条件,同步;此外更远大的用法包括:尾调用消除,记忆化甚至改进修饰器的写作。

为了增强代码的可读性,可以在函数后书写“文档字符串”(简称docstrings),用于解释函数的作用、参数的类型与意义、返回值类型与取值范围等。可以使用内置函数help()打印出函数的使用帮助。自从Python 3.5,开始支持类型提示,可以标注函数的参数与返回值。此特性可方便IDE对源代码进行更深入的分析。

对象及其方法

Python支持大多数面向对象编程技术。在Python中所有东西都是对象,包括类、函数、数和模块。它允许多态性,不只是在类层级之内而且通过采用鸭子类型的方式。任何对象可以用于任何类型,只要它有适当的方法和特性(attribute)就能工作。Python天然支持类的继承包括多重继承,为此采用C3线性化或方法解析次序(MRO)算法,还支持mixin。Python支持元类,它是增进类的功能的高级工具。

Python使用名字修饰有限的支持私有变量。对象的特性可以被提取为一个字典。在Python中不强制使用访问子与变异子方法来访问数据成员的面向对象编程信条。就像Python提供函数式编程构造但不尝试要求参照透明性(无副作用)一样,它提供对象系统但不要求面向对象编程行为。

对象的方法是附属于这个对象的类的函数。对于正常的方法和函数,语法instance.method(arguments),是Class.method(instance, arguments)的语法糖。Python的方法有显式的self形式参数用来访问实例数据,对比于在其他一些面向对象编程语言(比如C++、Java、Objective-C或Ruby)中隐式的selfthis关键字。在Python中,self可以被看作是一个习惯用法,它可以被换为任何其它合法的参数名。

Python支持一些以__开始和结束的特殊方法名,它们用于实现运算符重载和实现多种特殊功能。在Python中,可以通过定义特殊方法来重载运算符,比如在一个类上定义__add__()将允许在这个类的实例上使用+算符。在Python中,当一个子类的方法覆盖了超类方法的时候,通过调用super().method来调用与子类的self.method方法同名超类方法。

Python允许通过使用@classmethod@staticmethod修饰符来分别创建类方法和静态方法。给类方法的第一个实际参数是类对象而非对实例的self引用。静态方法没有特定的第一个实际参数,实例或类对象都不固定的传递给静态方法。

在Python中定义了一个或多个特殊方法__get__()__set__()__delete__()的类可以用作描述器(descriptor)。如此创建一个描述器的实例作为另一个类的一个类成员,使得这个实例成为此另一个类的属性(property)。使用与特性(attribute)访问相同的语法,访问一个实例对象中的这个成员属性。 Python的property内建函数,将一个类中特殊定义的访问一个特性的那些方法包装成的这个类的一个属性。

类型

Python使用鸭子类型并拥有有类型的对象和无类型的变量名字。在编译期不检查类型约束,而宁愿在一个对象上的操作出现可能的失败,表现出这个给定对象不具有适合的类型。尽管是动态类型系统,Python却是强类型的,禁止没有明确定义的操作(比如加一个数到一个字符串),而不是默默的去尝试转换使其有意义。Python支持广泛的类型和类的内省。类型是type的实例,可以被读取和比较。

Python有着范围广泛的基本数据类型。同时具备常规的整数和浮点算术,它透明的支持任意精度算术、复数和十进制浮点数。Python支持种类繁多的字符串操作。在Python中字符串是不可变的,所以在其他编程语言中可能就地改变字符串的字符串操作比如字符替换,在Python中返回新的字符串。

Python的一个非常有用方面就是搜集(或称容器)类型的概念。一般的说,搜集是以一种易于引用或索引的方式包含其他对象的对象。Python对创建容器类型的对象有着语法上的支持。搜集有二种基本形式:序列和映射。有次序的序列类型是列表(动态数组)、元组和字符串。所有序列类型都是位置索引的(从0到长度−1),并且除了字符串,都可以包含任意类型的对象,在同一个序列中包括多种类型的对象。字符串和元组是不可变的,使得它们成为字典的键的完美候选者。在另一方面,列表是可变的,元素可以被插入、删除、修改、添加或就地排序。

在另一方面,映射是以“字典”形式实现的无次序的类型,它将一组不可变的键映射到相应的元素上(非常像数学函数)。在字典中的键必须是不可变的Python类型,比如整数或字符串,因为在底层它们是通过散列函数实现的。字典还是语言内部的中心,因为它们居于所有Python对象和类的核心:在变量名字(字符串)和这个名字所引用的值之间的映射就存储为字典,而这些字典可以通过对象的__dict__特性直接访问。

集合搜集类型是在版本2.4中增加入语言核心的。集合是不包含重复项的无索引、无次序的搜集,并且实现了集合论运算比如并集、交集、相对补集、对称差和子集测试。有二种类型的集合:可变的set和不可变的frozenset。集合中元素必须是可散列的,比如说,frozenset可以是正规set的元素而反之不行。Python还提供了广泛的搜集操纵能力比如内建的包含元素检查和通用迭代协议。

Python允许编程者使用类定义自己的类型,类在面向对象编程中是最经常使用的。类的新实例是通过调用这个类的构造器而创建的,而类都是元类type的实例,typetype元类自身的实例,这允许了元编程和反射。

在版本3.0之前,Python有两种类:旧式的和新式的。二种样式的语法是一样的,不同在于是否直接或间接的继承自类object,所有新式类都从object继承并且是type的实例。在Python 2系列2.2以上,二种类都可以使用。在Python 3.0中淘汰了旧式类。

长期规划是支持渐进类型,并且自从Python 3.5,语言的语法允许指定静态类型,但在缺省实现CPython中不检查它们。有实验的叫做“mypy”的可选的静态类型检查器支持编译期类型检查。

类型可变性描述语法例子
bool不可变布尔值True
False
int不可变理论上无限制大小的整数42
float不可变双精度浮点数。精度是机器依赖的但实际上一般实现为64位IEEE 754数而带有53位的精度1.414
complex不可变复数,具有实部和虚部3+2.7j
range不可变通常用在循环中的数的序列,规定在for循环中的次数range(1, 10)
range(10, -5, -2)
str不可变字符串,Unicode代码点序列

'Wikipedia'
"Wikipedia"
 

"""Spanning
multiple
lines"""
bytes不可变字节序列b'Some ASCII'
b"Some ASCII"
bytes([119, 105, 107, 105])
bytearray可变字节序列bytearray(b'Some ASCII')
bytearray(b"Some ASCII")
bytearray([119, 105, 107, 105])
list可变列表,可以包含混合的类型[4.0, 'string', True]
[]
tuple不可变元组,可以包含混合的类型(4.0, 'string', True)
('single element',)
()
dict可变键-值对的关联数组(或称字典);可以包含混合的类型(键和值),键必须是可散列的类型{'key1': 1.0, 3: False}
{}
set可变无序集合,不包含重复项;可以包含混合的类型,如果可散列的话{4.0, 'string', True}
set()
frozenset不可变无序集合,不包含重复项;可以包含混合的类型,如果可散列的话frozenset([4.0, 'string', True])
types.EllipsisType不可变省略号占位符,用作NumPy数组的索引...
Ellipsis
types.NoneType不可变表示值缺席的对象,在其他语言中经常叫做nullNone
types.NotImplementedType不可变可从重载运算符返回的占位符,用来指示未支持的运算数(operand)类型NotImplemented

除了各种数据类型,Python解释器内建了还有很多其他类型,比如上下文管理器类型,模块、方法、代码对象、类型对象、内部对象等类型。

数学

Python的算术运算使用平常的符号+-*/,下取整除法算符//和模除%(这里的余数可以是负数,比如4 % -3 == -2)。它还有指数算符**,比如5**3 == 1259**0.5 == 3.0,和矩阵乘法算符@。这些算符就像在传统数学中一样运算,具有同样的优先级规则,中缀算符+-还可以分别表示取原数和取相反数的一元算符。

在整数之间的除法/产生浮点数结果。除法/的表现随着版本不同而有着显著变化。

Python提供了round()函数用于把一个浮点数修约成最近的整数。

Python允许由比较运算链接起来的布尔表达式表现得如在数学中常用的一样。比如,表达式a < b < c测试a小于b并且b小于c。C派生语言不一样的解释这个表达式:在C中,这个表达式将首先求值a < b,结果为01,接着把这个结果比较于c

Python对所有整数运算使用任意精度算术。在decimal模块中的Decimal类型/类提供十进制浮点数到预定义的任意精度并有多种修约模式。在fractions模块中的Fraction类提供任意精度的有理数。

由于Python有着广泛的数学库,除了求绝对值函数abs()列入内建函数之外,大多数数学函数处于mathcmath模块内。前者用于实数运算,而后者用于复数运算。特别是,第三方库NumPy进一步扩展了固有能力,Python经常被用作科学脚本语言来处理如数值数据处理和操纵等问题。

标准库

Python拥有一个强大的标准库。Python语言的核心只包含数值、字符串、列表、字典、文件等常见类型和函数,而由Python标准库提供了系统管理、网络通信、文本处理、数据库接口、图形系统、XML处理等额外的功能。

Python标准库的主要功能有:

  • 文本处理,包含文本格式化、正则表达式、文本差异计算与合并、Unicode支持,二进制数据处理等功能。
  • 文件系统功能,包含文件和目录操作、创建临时文件、文件压缩与归档、操作配置文件等功能。
  • 操作系统功能,包含线程与进程支持、IO复用、日期与时间处理、调用系统函数、日志(logging)等功能。
  • 网络通信,包含网络套接字,SSL加密通信、异步网络通信等功能。支持HTTP,FTP,SMTP,POP,IMAP,NNTP,XMLRPC等多种网络协议,并提供了编写网络服务器的框架。
  • W3C格式支持,包含HTML,SGML,XML的处理。
  • 其它功能,包括国际化支持、数学运算、HASH、Tkinter等。

程序代码实例

一个在标准输出设备上输出Hello World的简单编程,这种编程通常作为开始学习编程语言时的第一个编程,可将如下代码录入纯文本文件并随意命名比如program01.py,然后执行这个程序python3 program01.py

print("Hello, world!")

Python也可以单步解释执行。执行Python解释器进入交互式命令行的环境,你可以在提示符号>>>旁输入print("Hello, world!"),按Enter键输出结果:

>>> print('Hello, world!')
Hello, world!

计算正数的阶乘的程序代码:

n = int(input('键入一个数,就会打印它的阶乘: '))
if n < 0:
    raise ValueError('错误,输入不正确!请输入一个非负数')
fact = 1
for i in range(2, n + 1):
    fact *= i
print(fact)

注意,在Python 3.0及以上版本中,print是个函数,需要在要打印的字符串前后加上圆括号;在Python 2.6以下版本中,print是一个关键字和命令而不加圆括号。

实现

Python是一门跨平台的脚本语言,Python规定了一个Python语法规则,根据该规则可编写Python解释器。Python属于动态语言,将Python程序编译成中间形式的字节码,并接着在它的虚拟机上执行,相较于C/C++等编译成机器码的编译语言而言运行速度较慢。

主要实现

  • CPython:官方的解释器,需要区别于其他解释器的时候才以CPython称呼。
  • MicroPython和CircuitPython:它们是为微控制器而优化的Python 3变体。
  • Pyston:CPython 3.8的分叉,具有包括JIT的额外性能优化,还将其JIT部分作为扩展模块pyston_lite_autoload来单独发行。
  • Cinder:由Meta开源发布,它是Meta内部使用的面向性能的CPython 3.8分叉,具有包括JIT的很多优化。
  • PyPy:用RPython书写的Python实现,其稳定版本兼容至CPython 3.8,它采用了跟踪JIT,缺省支持stackless模态。
  • Stackless Python:实现微线程的CPython 3.8分叉,它不使用C内存堆栈,因而允许大规模并发程序。

到其他语言的交叉编译器

  • Cython:将扩充了静态类型的Python超集编译成C或C++。
  • Numba:使用LLVM,将包括很多NumPy函数的聚焦数值计算的Python子集,翻译成快速的机器码,它为在CPU和GPU上并行化Python代码提供了大量选项。
  • Pyjion:CPython的JIT扩展,它将Python代码编译成本机CIL,从而使用.NET CLR来执行它。
  • Nuitka:用Python书写的到C11或C++03的优化编译器,它能创建不需单独的安装器就能运行的可执行程序。
  • Pythran:将聚焦于科学计算的Python子集编译成C++11的提前编译器,它能利用上多核和SIMD指令单元。
  • MyHDL:将Python编译成VHDL。

仍在维护中的旧版本实现有:IronPython,它是面向.NET和Ecma CLI的Python 2.7实现,它还有处在开发状态的3.4版本实现;Jython,它是用Java实现的Python 2.7。

开发环境

通用文本编辑器

很多并非集成开发环境软件的文本编辑器,也对Python有不同程度的支持,并且加上专门为Python设计的编辑器插件也会有很高的可用性。

  • Visual Studio Code
  • Atom
  • Eclipse
  • IntelliJ IDEA
  • emacs
  • NetBeans
  • SlickEdit
  • TextMate
  • Vim
  • Sublime Text
  • EditPlus
  • UltraEdit
  • PSPad
  • Notepad++

专用开发环境

适用于Python的集成开发环境(IDE)软件,除了标准二进制发布包所附的IDLE之外,还有许多其他选择。其中有些软件设计有语法着色、语法检查、运行调试、自动补全、智能感知等便利功能。由于Python的跨平台出身,这些软件往往也具备各种操作系统的版本或一定的移植性。

  • IDLE:Python“标准”IDE,一般随Python而安装,支持较少的编辑功能,调试功能也比较弱。
  • Eric:基于PyQt的自由的IDE,支持自动补全、智能感知、自动语法检查、工程管理、svn/mercurial集成、自动单元测试等功能,具有可扩展的插件系统,通过可选插件支持Git集成。调试功能与Visual Studio和Eclipse类似。
  • Spyder:开源的跨平台科学计算IDE。
  • PyScripter:功能较全的开源IDE,使用Delphi开发。
  • PyCharm:由JetBrains公司出品,具备一般IDE的功能,比如调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制等等,另外,它还提供了一些功能用于Django开发,同时支持Google App Engine,还支持IronPython。它是商业软件,但也具有社区版和教育版。
  • Komodo和Komodo Edit:后者是前者的免费精简版。
  • WingIDE:商业软件,有免费的功能有限的Wing IDE 101,适用于入门者教学。

应用

在很多操作系统里,Python是标准的系统组件。大多数Linux发行版和macOS都集成了Python,可以在终端下直接执行Python。虽然Python可被粗略地分类为脚本语言,Python的支持者较喜欢称它为一种高端动态语言,常像“胶水”一样被用来连接软件组件,已经显著的区别于Unix shell、Windows PowerShell这样的语言。基于Python的xonsh,是跨平台的、青睐Unix的shell语言和命令行界面。

Python社群提供了大量的功能覆盖众多领域的第三方模块,其使用方式与标准库类似。第三方模块可以使用Python/Cython或者C编写。软件工具SWIG和SIP,通过定义接口文件或规定文件的方式,可以将C/C++编写的程序库包装为Python模块。Python解释器本身也可以被集成到其它需要脚本语言的编程内。

pip是事实标准和官网推荐的用Python书写的软件包管理系统,它通常连接到叫做Python包索引的一个公开软件包在线仓库。pipenv自动为用户项目创建和管理虚拟环境,还在安装/卸装软件包的时候,向Pipfile文件增加/移除这个软件包。pyenv可以安装并轻易切换多个版本的Python。

自从2003年,Python始终排行于TIOBE编程社区索引前十最流行编程语言,在2021年10月它首次达到了第一名最流行语言(居于C和Java之前),并被选为2007年、2010年、2018年、2020年和2021年的年度编程语言。

网络服务

Python定义了WSGI标准应用接口来协调Http服务器与基于Python的Web编程之间的沟通。比如,通过mod_wsgi模块,Apache可以运行用Python编写的Web编程。Zope是著名的用Python编写的开源的Web应用服务器。Tornado是用Python语言写成的非阻塞式web服务器,也是轻量级的Web框架。

Python对于各种网络协议的支持很完善,因此经常被用于编写服务器软件、网络爬虫等Web开发。用Python编写的一些Web框架,可以让程序员轻松地开发和管理复杂的Web编程。著名的第三方Web框架和函数库:

  • Django:MTV架构的Web开发框架,注重组件的重用性和“可插拔性”、快速开发和DRY法则。
  • web2py:MVC架构的全栈Web框架,聚焦于快速开发,偏好约定优于配置方式。
  • TurboGears:MVC架构的混合Web框架,可以担任全栈框架或微框架二者。
  • Pyramid:极简主义的Web框架,不预定持久化方式,它是Pylons计划的一部分。
  • Flask:微Web框架,不要求特定的工具或库。
  • aiohttp:轻量级的Web框架,采用的是Python3的asyncio异步特性。
  • Twisted:事件驱动的网络编程框架。它支持多数标准的网络协议(包含客户端和服务器),并且提供了多种工具,被广泛用于编写高性能的服务器软件。
  • Requests:适合于常人使用的HTTP库,封装了许多繁琐的HTTP功能,极大地简化了HTTP请求所需要的代码量。
  • Beautiful Soup:用来解析HTML/XML的一个简单易用Python包。
  • gevent:是基于协程的高性能并发网络编程库,使用greenlet在libev或libuv之上提供了高层的同步式API。

图形用户界面

Python本身包含了Tkinter库,它是Python的业界标准GUI并被集成进入了IDLE。Tkinter基于了Tcl命令工具,能够支持简单的GUI开发。但是越来越多的Python程序员选择第三方GUI包来开发跨平台的桌面软件,使用它们开发的桌面软件运行速度快,与用户的桌面环境相契合。著名的第三方GUI库:

  • PyQt:Qt的Python绑定库,由Riverbank Computing公司自从1998年发行,采用GPL许可证或商业许可证。
  • PySide:Qt的Python绑定库,由Qt公司自从2009年发行,采用LGPL许可证。
  • PyGObject:替代了PyGTK,为Python程序访问基于GObject的库提供了包装库,GObject是GTK、GIO和GStreamer等库使用的对象系统。
  • Kivy:用于开发多点触控应用软件的开源Python库,采用了自然用户界面(NUI)。
  • WxPython:GUI编程框架wxWidgets的Python包装库,它与MFC的架构相似。
  • PySimpleGUI:将Tkinter、Qt、WxPython和Remi的GUI框架变换成简单的接口。
  • Gooey:将几乎所有Python 3控制台程序用一行代码转变成GUI应用。
  • Pyforms:开发能够在三种不同环境即桌面GUI、终端和网页下执行的程序的Python框架。

数据科学

重要的数据科学用第三方软件库有:

  • NumPy:Python的基础性的科学计算软件库,提供了矩阵、线性代数、傅立叶变换等的解决方案。
  • SciPy:用Python实现了MATLAB所有功能的软件库,使用NumPy的多维阵列作为基本数据结构。
  • CuPy:NumPy/SciPy兼容的GPU加速的阵列库,它可在NVIDIA CUDA或AMD ROCm平台上充当其即插即用替代者,来运行现存的NumPy/SciPy代码。
  • pandas:用于数据分析和数据操纵的软件库,建造在NumPy基础上,提供了类似于R语言中同名对象的加标签数据结构“数据帧”,和统计函数等。
  • Dask:伸缩范围从笔记本电脑至计算机集群的并行计算库,它由两部分构成:为计算而优化的动态任务调度,和“大数据”搜集如并行的阵列、数据帧和列表。这些搜集将常用接口如NumPy、pandas或Python迭代器,扩展到大过内存或分布式的环境,并行的搜集运行在动态任务调度器顶上。
  • matplotlib:用于Python和NumPy的绘图库,实现类似MATLAB的绘图功能。
  • scikit-learn:基于NumPy、SciPy、Joblib和threadpoolctl的机器学习软件库,实现许多知名的机器学习算法,其绘图功能依赖于matplotlib。
  • Dash:基于React、Flask和Plotly公司的Plotly.js之上的框架,它将现代用户界面元素如下拉选单、滑动条和图形,直接链接至分析型Python代码。它和Streamlit、Panel和Voilà,是被称为“仪表板”的数据可视化工具。
  • PyMC:基于Theano的概率编程库,用于贝叶斯统计建模和概率机器学习。
  • TensorFlow:Google开发的一个端到端开源机器学习平台,它提供了Python API,其中实现了Keras API。Keras现在是在TensorFlow 2上创建的深度学习高层API。SciKeras是对Keras模块的scikit-learn兼容的包装器。
  • PyTorch:Meta在Torch基础上开发的开源的Python软件包,提供了具有强大的GPU加速的张量计算,和创建在基于tape的自动梯度系统上的深度神经网络。skorch是包装了PyTorch的scikit-learn兼容的神经网络库。
  • JAX:Google开发的拥有可组合的函数变换的开源机器学习框架,结合了修改版本的针对NumPy的自动梯度库Autograd,和TensorFlow中的加速线性代数库XLA,它使用XLA来在GPU和TPU上编译和运行NumPy程序。JAX除了用于开发新的人工神经网络软件库比如Flax,还用于概率编程库比如NumPyro,和物理引擎比如Brax。
  • Ray:对人工智能及Python应用的运行规模进行伸缩的统一框架。它构成自一个核心的分布式运行时间系统,和加速机器学习工作负载的软件库工具箱(Ray AIR)。它支持TensorFlow或PyTorch,可集成于Dask、Apache Spark和Mars,可以部署在Kubernetes集群和云端VM之上。

其它种类的库

  • SymPy:支持数学符号运算如微积分等的软件库,用于提供计算机代数系统。
  • SQLAlchemy:针对关系型数据库的对象关系映射(ORM)工具。
  • Pillow:是基于Python的图像处理库,它支持广泛的图形文件格式,分叉于已终止的PIL。
  • PyOpenGL:到OpenGL 1.1-4.4和有关API的最常用跨平台Python绑定。
  • ModernGL:在OpenGL 3.3+核心上的Python包装器,它简化了简单图形应用如科学模拟、游戏和用户界面的创建。
  • VisPy:高性能交互式2D/3D数据可视化库,它通过OpenGL库利用现代GPU的计算能力来显示非常大的数据集。
  • PyCUDA和PyOpenCL:不同于Nvidia尽可能匹配C API的cuda-python,PyCUDA提供对CUDA并行计算API的Python风格访问;PyOpenCL提供对OpenCL并行计算API的Python风格访问。
  • Kornia:基于PyTorch的可微分计算机视觉库。
  • pygame:开发视频游戏的Python软件库,基于了SDL库。
  • pyglet:Python编写的面向对象的游戏和多媒体库,利用了FFmpeg库。
  • pythonnet:针对.NET的程序包,它可以近乎无缝的集成.NET通用语言运行库(CLR)。
  • Fabric:经由SSH远程执行shell命令的高层库,它产生有用的Python对象作为回馈。
  • Prefect:现代工作流程编排框架,它易于建造、调度和监控健壮的数据流水线。
  • PyInstaller:将Python应用和它的依赖项捆绑成一个单一的包,从而不需要安装Python解释器或任何模块就可以运行应用。

应用软件

有一些Linux发行版的安装器使用Python语言编写。在RPM系列Linux发行版中,有一些系统组件就是用Python编写的。一些著名的互联网公司在内部大量地使用Python。一些游戏比如EVE,使用Python编写游戏的逻辑、服务器。如下著名应用使用Python编写或将它作为嵌入式脚本:

  • IPython:以多种编程语言进行交互式计算的命令shell和Jupyter的内核,最初为Python开发,它提供了内省、富媒体、shell语法、tab补全和历史。
  • Conda:跨平台的、语言无关的二进制包管理器,它被Anaconda发行采用。
  • SCons:软件建造工具,它可代替make构建编译程序。
  • Ubiquity:Ubuntu的安装器。
  • Anaconda:Red Hat Enterprise Linux和Fedora的安装器。
  • Portage:Gentoo Linux使用Python编写的软件包管理系统。
  • Gunicorn:使用Python语言编写的WSGI Web服务器。
  • Plone:基于Zope的内容管理系统。
  • Mezzanine:基于Django框架的内容管理系统。
  • Odoo:ERP软件,有开源社区版。
  • SageMath:覆盖许多数学功能的应用软件。
  • Veusz:用Python、PyQt和NumPy写成的科学绘图软件,可生成能够出版的PDF或SVG输出。
  • LibreOffice:自从2013年的版本4.0开始,包含了Python并意图用它来替代Java,它的Python脚本提供器是核心特征。
  • Blender:开源3D绘图软件,使用Python作为建模工具与GUI语言。
  • Inkscape:开源的SVG矢量图形编辑器,使用Python用于插件。
  • Panda3D:开源游戏引擎,包括了图形、音频、I/O、碰撞侦测和其他与3D游戏有关的功能,使用Python作为游戏开发语言。

社群流行

  • PyCon:各地社群举办的会议,通常每年举办。各社群在会议中讨论Python相关的议题。
  • Python Discord:参与者众多的Python社区。
  • PyLadies:由女性社群发起的社群,主要注重于发展Python的女性程序设计社群。
  • Django Girls:使用Django网页设计框架,推广使用Python进行网页设计的技术。

影响的语言

Python的设计和哲学已经影响了很多其他编程语言:

  • Boo:使用了缩进、类似的语法和类似的对象模型。
  • Cobra:使用了缩进和类似的语言,而且它的致谢文档将Python列为影响它的首要语言。
  • CoffeeScript:是交叉编译至JavaScript的编程语言,有受Python启发的语法。
  • ECMAScript/JavaScript:从Python借鉴了迭代器和生成器。
  • GDScript:是非常类似Python的脚本语言,内置入了Godot游戏引擎。
  • Genie:基于Vala编译器的具有近似Python语法的一种语言。
  • Go:设计为“有动态语言如Python的工作速度”,并共享了相同的分片数组的语法。
  • Groovy:受到Python等动态类型语言的影响。
  • Nim:使用缩进和类似的语法。
  • Swift:是Apple开发的编程语言,有受Python启发的语法。

Ruby的创建者松本行弘曾说过:“我想要一种脚本语言,比Perl更加强力而且比Python更加面向对象,因此我决定设计自己的语言”。Julia设计原则中有一条是:“像Python一样可用于通用编程”。