掌握Python:编程新手的必修课

发表时间: 2023-08-26 09:11

Python为了让代码具备高度的可阅读性,在设计时尽量使用了其它语言常用的符号和英文单字。Python支持使用反斜杠作为行接续符,将多个物理行合成为一个逻辑行。在圆括号、方括号或花括号之中的表达式,可以分裂跨越多于一个物理行而不使用反斜杠,这被称为“隐式行接续”。注释开始于并非字符串文字一部分的一个井号#,并结束于物理行结尾;注释标示逻辑行的结束,除非已受制于隐式行接续规则;注释在语法上被忽略。简单语句包含在一个单一的逻辑行之内,Python支持使用分号作为分隔符,将多个简单语句合并入语法意义上的一行之中

Python语法中的复合语句,包含(成组的)其他语句;它们以某种方式影响或控制这些其他语句的执行。Python的复合语句包含一个或多个子句(clause),子句构成自一个头部(header)和一个包(suite)。特定复合语句的子句头部都在同样的缩排层级上,每个子句头部开始于一个唯一标识关键字,并结束于一个冒号。包是这个子句所控制的一组语句,包有两种形式,可以是与头部在同一行上的一个或多个由分号分隔的简单语句,它们跟随在这个头部的冒号之后;或者是在后续诸行上的一个或多个缩排的语句,只有这种包形式可以包含嵌套的复合语句


缩进


Python语言遵循越位规则,利用缩进来形成语句包,即语法意义上的块。连续诸行的缩排层级,被用来生成语法解析器才能见到的INDENT和DEDENT记号

,二者的作用相当于C语言家族的花括号,或Pascal语言家族的关键字begin和end。增加缩进就生成INDENT记号,减少缩进就生成DEDENT记号。根据PEP 8的规定,使用4个空格来表示每级缩进。tab字符(从左至右)被替代为1至8个空格,使得直到tab之前的诸字符加上这些替代空格的字符总数,是8的倍数(这意图同于Unix所用规则)。前导于第一个非空白字符的空格的总数,确定了这一行的缩排层级。缩排所用诸字符,不能使用反斜杠来拆分成多个物理行;直到第一个反斜杠之前的空白确定缩排层级。如果源代码文件混合了tab和空格,并且在这种方式下缩排的意义依赖于一个tab相当于多少个空格,则这种缩排因不一致性而被报错并拒绝


关键字


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





内建常量True、False和None于Python 3.0中成为关键字,关键字nonlocal介入于Python 3.0

,关键字async和await介入于Python 3.5,并在Python 3.7中成为正式关键字

标识符match、case和通配符_介入于Python 3.10,它们在与模式匹配语句有关的上下文中,可以在语法上充当关键字;但是这种区分只在语法解析器层次进行,并非在词法分析记号化层次。在Python中,只在特定上下文中保留的这种标识符,叫做“软关键字”


标识符


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

,是为“保留标识符类”


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


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


语句


Python的语句包括简单语句:


  • 赋值语句,记号为等号=。赋值语句被用来将名字绑定(含重新绑定)到值,以及用来修改可变对象的特性或项目。Python还支持增广赋值语句

,将一个二元运算和一个赋值语句合并成一个单一语句,例如x += 1。Python支持“序列解包”(sequence unpacking):在等号左侧可以是一个表达式列表,其中每个表示式都可求值成能被赋值的东西(变量、可写特性等);在等号右侧相应的是一个“可迭代”对象,它在被迭代时产生的值的数量,同于左手侧可写表达式的数量;赋值语句对这个对象进行迭代,将产生的每个值分别赋值给左侧对应的可赋值者。在等号右侧直接包装出序列解包所要求的元组,就形成了并行赋值,可以同时给多个变量赋值,还可以交换两个变量的值。

  • 表达式语句,用来交互式的计算并写出一个值,或者用来调用一个过程(即返回无含义结果的函数),在Python中过程返回值None。

  • global语句,是在整个当前代码块中成立的声明,它意味着随后列出的标识符被解释为全局变量。

  • nonlocal语句,导致随后列出的标识符,提及在除了全局作用域之外的最近包围作用域中的先前绑定变量。

  • pass语句,充当NOP,表示此行为空,不执行任何操作。

  • assert语句,用于编程调适阶段时测试执行条件是否满足。

  • continue语句,越过这次迭代并继续进行下个项目。

  • break语句,从循环中跳出。

  • return语句,用来从函数返回值。当函数执行到return语句时,它会停止执行并将指定的值返回给调用者。

  • raise语句,抛出一个异常。

  • yield语句,使用它从一个生成器中返回一个值。在版本2.5之前,信息只能单向的从生成器传递出来。
  • 自此版本2.5,重定义yield为表达式,通过它的返回值将信息传递进入生成器函数中,从而能够支持协程功能。自从版本3.3,提供了yield from语句,含有这个语句的“委托生成器”将其部分运算委托给另一个“子生成器”,将传入信息递送给它并直接回传它产生的值。yield语句在语义上等价于加圆括号的yield表达式。版本3.4在异步I/O框架中扩展了基于生成器的协程,这个扩展自从Python 3.8已经被弃用。版本3.6介入了异步生成器


  • import语句,导入一个模块或包,它组合了两种操作,查找指名的模块,接着将找到的结果绑定到在局部作用域中的名字。导入语句有三种形式:import 模块名字 [as 别名],找到一个模块,装载它,如果有需要的话初始化它;在这个导入语句出现的作用域的局部命名空间中,定义一个名字或一些名字
  • 。from 模块名字 import 定义1 [as 别名1], 定义2 [as 别名2], ...,找到、装载、必需时初始化一个模块;接着在局部命名空间中,增加到找到指名特性的引用。(这二个语句示例中的方括号表示其中内容为可选的。)from 模块名字 import *,在导入语句出现的作用域的局部命名空间中,绑定模块中定义的所有公开的名字

    • del语句,递归的进行删除。


    复合语句:


    • if语句,当条件成立时执行语句包。它经常包含elif、else子句。
    • while语句,当条件为真时,重复执行语句包。
    • for语句,遍历列表、字符串、字典、集合等迭代器,依次处理迭代器中的每个元素。
    • match语句,用于模式匹配。
    • try语句,它经常包含except、else、finally子句,处理在编程执行中出现的异常情况。Python支持并广泛使用异常处理,作为检测错误状况和程序中其他“异常”事件的方式,并提倡在可能出现错误状况的任何时候都使用异常。习惯上访问一个文件或资源不在使用之前进行测试,而是先行尝试使用它,再捕获访问被拒绝引发的异常。

    with语句,把一块代码包裹在一个上下文管理器之内。它允许了资源获取即初始化(RAII)式行为,可替代常见的try/finally惯用法。Python使用with语句处理资源,在进入一个作用域的时候调用一个函数,而在离开它的时候调用另一个函数,例如:在一块代码执行之前获取一个锁,并且在此后释放这个锁;或事先打开一个文件,并且事后关闭它。

  • class语句,是定义类的可执行语句。类的继承列表给出基础类列表,没有继承列表的类,缺省继承基础类object。类的包接着在新的执行框架(frame)中执行,它使用新建的局部命名空间和原来的全局命名空间。当这个类包完成执行之时,丢弃它的执行框架并保存它的局部命名空间。一个类对象接着被创建,其基础类采用继承列表,其特性字典采用保存的局部命名空间。类名字接着在原来的局部命名空间中,被绑定到这个类对象。

  • def语句,是定义函数和方法的可执行语句。它的执行在当前局部命名空间中,将函数名字绑定到一个函数对象(对函数的可执行代码的包装器)。这个函数对象包含到当前全局命名空间的引用,作为调用这个函数时使用的全局命名空间。

  • async def语句,用于协程函数定义。await表达式、async for语句和async with语句,只能用在协程函数的主体中。
  • 模块是包含Python定义和语句的一个文件,这个文件名字是模块名字附加上后缀.py;在一个模块中,模块的名字(作为字符串)可获得为全局变量__name__的值。内建globals()函数,返回实现当前模块命名空间的字典。内建dir()函数,在无参数时,返回在当前局部作用域内的名字列表;在有一个参数时,尝试返回这个对象的有效特性的列表。包(package)是可以包含子模块或递归的子包的模块。包在技术上是具有__path__特性的Python模块。可以将包视为文件系统上的目录,而将模块视为这种目录中的文件,但是包和模块不必然源自文件系统

    Python程序构造自代码块。代码块是作为一个单元执行的Python程序文本。模块、函数主体和类定义都是块。交互式键入的每个命令都是块。脚本文件和脚本命令是代码块。__main__是顶层代码运行所在的环境。“顶层代码”是启动运行的首个用户指定Python模块。从命令行使用-m参数,作为顶层脚本运行的模块(作为模块__main__)也是代码块。此时__name__变量被设置为"__main__",在这个模块中可籍此增加直接运行时候执行的代码

    。传递给内建函数eval()和exec()执行的字符串是代码块。

    在Python中赋值所进行的操作,是将一个名字绑定为到一个分立的动态分配的对象的一个引用。名字是通用的引用持有者,它不关联于一个固定的数据类型,但是,一个名字在给定时间,总是被绑定到有一个类型的某个对象上,这就是动态类型的特征。名字的存储位置不“包含”所指示的值,一个共同的值可以赋值给多个名字,一个名字在任何时候,都可以重新绑定到各种不同类型的对象上,包括字符串、过程、具有数据和方法的复杂对象等。

    除了在块中出现的每个赋值语句或导入语句之外,下列构造也绑定名字:给函数的形式参数、类定义、函数定义、赋值表达式、在for语句头部中和各种as关键字之后的标识符目标(target),as关键字出现在import语句、with语句、except子句、except*子句和结构式模式匹配的as模式之中。如果一个名字绑定在一个块中,它是这个块的局部变量,除非被声明为nonlocal或global。如果一个名字绑定在模块层次,它是全局变量;模块代码块的变量,既是局部的也是全局的。如果一个变量使用在一个代码块中,却不定义在这里,它是自由变量

    作用域定义一个名字在一个块中的可见性。如果一个局部变量被定义在一个块中,它的作用域包括这个块。如果这个定义出现在一个函数块中,作用域扩展到在所界定作用域内包含的任何块,除非所包含的块为这个名字介入了不同的绑定。当一个名字在一个代码块之中使用,它采用最近包围作用域来解析。对一个代码块可见的所有这种作用域的集合,叫做这个这个块的“环境”

    。如果一个名字绑定在一个块中,并且在其中于绑定之前就被使用,会导致一个错误。如果global语句出现在一个块之中,在这个语句中指定的所有名字,提及在顶层命名空间中这些名字的绑定。名字在顶层命名空间解析,首先查找全局命名空间,即包含这个代码块的模块的命名空间;未果查找内建命名空间,即模块builtins的命名空间。global语句与在同一个块中的名字绑定运算有同样的作用域。如果一个自由变量的最近包围作用域包含它的一个global语句,这个自由变量被当作全局的。 nonlocal语句导致相应的名字,提及在最近包围函数作用域内的先前绑定变量(即非局部变量)。

    表达式


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


    • 在Python中,算术运算的加法+、减法-、乘法*和取模%是与C语言和java相同的,但是除法的行为不同。在Python中有两种除法,它们是下取整除法(或整数除法)//和浮点除法/。Python增加了指数算符**。自从Python 3.5,介入了矩阵乘法算符@

    ,它已经用于了NumPy库


    • 在Python中,有如下必须用于整数的位运算:&与(AND),|或(OR),~非(NOT),^异或(XOR),>>右移, <<左移。


    • 在Python中,有如下比较运算:大于>,小于<,等于==,不等于!=,小于等于<=,大于等于 >=。==按值比较。Python的is、is not算符可以用来比较对象的同一性(按引用比较),也就是比较两个变量是否引用了同一个对象。而in、not in用于判断一个对象是否属于另外一个对象。在Python中,比较是可以链接起来的
    • ,比如a < b < c。


    • Python使用and、or、not表示逻辑运算与、或、非,不采用C语言和Java中所用的符号&&、||、!。


    • 在Python中,由逗号,分隔的一组表达式,叫做表达式列表。Python为构造列表、字典或集合,提供了叫做“显示”的特殊语法,它们每个都有两种方式:包容内容要么显式列举出来;要么通过一组循环和过滤指令计算而来,这叫做“推导式”。列表显示是包围在方括号中的可以为空的一系列表达式,一个例子列表可写为[1,2,3]。字典显示是包围在花括号中的可能为空的一系列的键/数据项对。集合显示用花括号来指示,与字典显示的区别是缺少分隔键与值的分号

    。自从Python 3.5,增加了在表达式列表中的“可迭代解包”*,和在字典显示中的“字典解包”**。

  • Python支持列表推导式。
  • Python 2.4将列表推导式扩展至更一般性的生成器表达式。Python 3.0又增补了字典推导式和集合推导式。

  • 在Python中,加圆括号形式(parenthesized form),是包围在圆括号中的一个可选表达式列表。加圆括号的表达式列表产生的东西,就是这个表达式列表所产生的:如果这个列表包含至少一个逗号,它产生一个元组;否则它产生构成这个表达式列表的那个单一表达式
    • 。一个例子元组可写为(1,2,3)。元组不是圆括号形成的,而是使用逗号形成的,在没有歧义的情况下,元组的圆括号是可选的。空的圆括号对产生空元组对象。使用序列串接算符+来串接二个元组,产生包含给定元组二者的元素的一个新元组。


    • Python支持在序列对象(比如字符串、元组或列表)上的下标(subscription)表达式:a[索引],和分片表达式:a[开始:停止]或a[开始:停止:步长]。下标索引是基于零的,负数是相对于结尾的。分片范围自从“开始”索引,直到但不包括“停止”索引。分片的第三个参数叫做“步长”(step)或“间隔”(stride),允许元素被跳过和用负数指示反向。分片索引可以省略,例如a[:],这返回整个列表的一个复本。
    • 分片的每个元素都是浅层复制的。


    • Python的条件表达式表示为x if c else y。意思是当c为真时,表达式的值为x,否则表达式的值为y。 在运算数的次序上不同于很多其他语言中常见的c ? x : y。


    • Python的匿名函数实现为lambda表达式。匿名函数体只能是一个表达式。
  • 自从Python 3.8,介入了赋值表达式,其记号是:=
  • 。它将一个表达式赋值给一个标识符,同时还返回这个表达式的值。赋值表达式在用作子表达式,即位于分片表达式、条件表达式、lambda表达式、关键字参数中的表达式和推导式中的if表达式之中,以及在assert和with语句之中的时候,必须围绕着圆括号。在它们可以使用的所有其他地方,包括在if和while语句之中,都不要求圆括号


    Python中运算符具有优先级,下表中的运算符按照从最高到最低的次序列出。在相同单元格中运算符具有相同的优先级,它们从左至右结合,除了指数表达式和条件表达式从右至左结合之外



    运算符描述

    (表达式...),[表达式...],{键: 值...},{表达式...}加圆括号表达式,列表显示,字典显示,集合显示

    x[索引],x[索引:索引],x(参数...),x.特性下标,分片,调用,特性引用

    await xawait表达式

    **指数

    +x,-x,~x取原数,相反数,逐位NOT

    *,@,/,//,%乘法,矩阵乘法,除法,下取整除法,余数

    +,-加法和减法

    <<,>>移位

    &逐位AND

    ^逐位XOR

    |逐位OR

    in,not in,is,is not,<,<=,>,>=,!=,==包含成员关系测试,同一测试,各种比较

    not x布尔NOT

    and布尔AND

    or布尔OR

    if – else条件表达式

    lambdalambda表达式

    :=赋值表达式



    Python提供了序列串接算符+和序列倍增算符*

    。自从Python 3.9,介入了字典归并算符|和字典更新算符|=

    Python的文本序列类型,包括字符串str和字节序列bytes与bytearray。字符串文字有多种写法,字符串对象有一个内建格式算符%:


    • 短字符串文字,由单引号'或双引号"界定。不同于Unix shell、Perl和受Perl影响的语言,单引号和双引号功能相同。这二种字符串都使用反斜杠\作为转义字符。


    • 长字符串文字,是开始并结束于三个单引号'''或三个双引号"""的序列。它们可以跨越多行,其功能就像shell、Perl和Ruby中的here文档。
    • 字节文字总是前缀上一个b或B,它产生bytes类型的实例。它们只可以包含ASCII字符,具有128或更大数值的字节必须通过转义来表达。


    • 字符串文字或字节文字都可选的能前缀上一个r或R,这叫做原始字符串。转义序列不被解释,因此在文字反斜杠常见的地方很有用,比如正则表达式和Windows风格的路径。
    • 这种引述可比较于C#中的“@引述”。


    • Python允许多个毗邻的字符串文字或字节文字(它们以空白分界并可以使用不同的引述约定),在编译时间于语法层面上串接起来。要在运行时间串接字符串,必须使用序列串接算符+

  • Python中的“字符串格式”算符%,在功能上类同于C语言中的printf格式化字符串
  • ,例如"spam=%s eggs=%04d" % ("blah", 2),求值为'spam=blah eggs=0002'。自从Python 3.0,str类提供了可供替代的format()方法,例如"spam={0} eggs={1:04d}".format("blah", 2)。在Python 3.6中,提供了“格式化字符串文字”或称为“f字符串”,它向字符串文字前缀上f或F,这是一种字符串插值,例如x="blah"; y=2; f'spam={x} eggs={y:04d}'。

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

    语句不能成为表达式的一部分,由于列表和其他推导式或lambda表达式,都是表达式,也就不能包含语句。这个限制的一个示例:赋值语句比如a = 1,不能用作条件语句的条件判断表达式的一部分;这能够避免C语言编程中的一个常见错误,即在条件判断时把等于算符==误写为赋值算符=,这不是预期代码却在语法上有效而能通过编译器检查,在Python中这会导致一个语法错误。


    函数


    Python的函数支持递归和闭包

    ,及其他头等函数特征,但不支持函数重载。Python的函数作为头等对象,具有和普通对象平等的地位。Python官方实现不提供尾调用优化或头等续体,吉多·范罗苏姆曾声称永远都不会加以支持,目前只有第三方库支持

    Python可以在函数定义时,于形式参数序列中,指定形式参数的缺省值,即以param=value样式进行一次性初始化。形式参数在初始化之后,保持既有绑定;函数的后续调用,可继续对它进行访问或变更。

    为有缺省值的形式参数提供实际参数,在函数调用时是可选的。

    Python的函数实际参数与形式参数之间的结合,是传递“对象引用”,函数在被调用的时候,给函数调用的实际参数,被介入到一个局部符号表中,实际参数使用传值调用来传递,而这个值总是对象引用,而非这个对象的值

    。如果形式参数绑定到一个可变的对象,则通过形式参数对此对象内容的修改,在函数外也是可见的。如果形式参数绑定到一个不可变的对象,则通过形式参数是不能修改此对象内容,但可以把形式参数重新绑定到其它对象上,这并不影响函数外的对象的值。Python支持位置实际参数和关键字实际参数。函数调用时,实际参数可以如同C语言那样,按照位置与形式参数匹配;也可以采用命名参数或称为关键字实际参数,即kwarg=value样式的实际参数。使用不对应实际参数的特殊形式参数/和*,可以将参数序列分为三部分:唯位置参数、可位置可关键字参数和唯关键字参数。有缺省值的形式参数之后,不能跟随无缺省值的可位置形式参数。

    在一个函数调用的实际参数序列中,关键字实际参数必须出现在位置实际参数之后。

    在位置和关键字形式参数序列末尾,可以分别有*args或**kwargs这样的形式参数,它们对应于在函数调用时提供的,超出形式参数序列规定而无所对应的多个实际参数;在形式参数名字前加一个*号,该形式参数args是tuple类型,对应可变量目的位置实际参数;在形式参数名字前加**号,该形式参数kwargs是dict类型,对应可变量目的关键字实际参数。

    如果位置实际参数已经在一个序列类型如列表或元组的对象中,在引用它的变量前加一个*号传递给函数,则其中所有元素解包为多个位置实际参数;如果关键字实际参数在字典中,则加**号来传递给函数。

    修饰器(decorator)可用来修改一个函数、方法或类定义的任何可调用Python对象。将已定义的原来对象传递给修饰器,它返回一个修改后的对象,接着把它绑定到在定义中那个名字。Python修饰器部分受到Java注解的影响,而有类似的语法;修饰器语法是纯粹的语法糖,使用@作为关键字形成修饰符。修饰器是一种形式的元编程,它们增强它们所修饰的函数或方法的行动。

    多个修饰器可以链接起来,通过在毗连的行上放置多个修饰符,或者使用中间变量。 函数修饰器的正规用法包括:用来建立类方法或静态方法、设置先决条件和后置条件、实现多方法、增加函数特性、跟踪、同步;此外更远大的用法包括:尾调用消除、记忆化

    为了增强代码的可读性,可以在函数后书写“文档字符串”(简称docstrings),用于解释函数的作用、参数的类型与意义、返回值类型与取值范围等。可以使用内置函数help(),打印出函数的使用帮助。

    自从Python 3.0,函数可以对参数与返回值增加类型标注。此特性可方便对源代码进行更深入的分析。自从Python 3.5,开始支持类型提示


    对象及其方法


    Python支持大多数面向对象编程技术。在Python中所有东西都是对象,包括类、函数、数和模块。它允许多态性,不只是在类层级之内,而且通过采用鸭子类型的方式

    。任何对象可以用于任何类型,只要它有适当的方法和特性(attribute)就能工作。Python天然支持类的继承包括多重继承,为此采用C3线性化或方法解析次序(MRO)算法,还支持混入。Python支持元类,自从Python 3.6,提供了定制类创建的简单机制

    Python使用名字修饰,有限的支持私有变量。对象的(可写)特性可以被提取为一个字典

    。在Python中,不强制使用访问子与变异子方法,来访问数据成员的面向对象编程信条。就像Python提供函数式编程构造,但不尝试要求参照透明性(无副作用)一样,它提供对象系统,但不要求面向对象编程行为。

    对象的方法,是附属于这个对象的类的函数。对于正常的方法和函数,语法instance.method(arguments),是Class.method(instance, arguments)的语法糖。Python的方法有显式的self形式参数,用来访问实例数据;这借鉴自Modula-3,对立于隐式的self或this关键字,它们用在其他一些面向对象编程语言,比如C++、Java、Objective-C或Ruby之中

    。在Python中,self可以被看作是一个习惯用法,它可以被换为任何其它合法的参数名。Python提供了super()内建函数,当一个子类的方法覆盖了超类方法的时候,可通过调用super().method,来调用与子类的self.method方法同名超类方法。 Python支持一些以__开始和结束的特殊方法名,它们用于实现运算符重载,以及实现多种特殊功能

    。在Python中,可以通过定义特殊方法来重载运算符,比如在一个类上定义__add__(),将允许在这个类的实例上使用+算符。

    在Python中,定义了一个或多个特殊方法__get__()、__set__()、__delete__()的类,可以用作描述器(descriptor)

    。建立一个描述器的实例,作为另一个类的一个类成员,使得这个实例成为此另一个类的属性(property)。使用与特性(attribute)访问相同的语法,访问一个实例对象中的这个成员属性。Python允许通过使用@classmethod和@staticmethod修饰符,来分别建立类方法和静态方法。给类方法的第一个实际参数,是对类对象的引用,而非对实例的self引用。静态方法没有特定的第一个实际参数,实例或类对象,都不固定的传递给静态方法。 Python的property内建函数,将一个类中特殊定义的访问一个特性的那些方法,包装成的这个类的一个属性。

    类型


    Python 3的标准类型层级

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

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

    Python有一个非常有用特征,就是搜集(或称容器)类型的概念。一般的说,搜集是以一种易于引用或索引的方式,包含其他对象的对象。搜集有二种基本形式:序列和映射。Python对建立容器类型的对象有着语法上的支持。

    Python还提供了广泛的搜集操纵能力,比如内建的包含元素检查和通用迭代协议。

    有次序的序列类型是列表(动态数组)、元组和字符串。所有序列类型都是位置索引的(从0到长度−1),并且除了字符串,都可以包含任意类型的对象,在同一个序列中包括多种类型的对象。字符串和元组是不可变的,使得它们成为字典的键的完美候选者。在另一方面,列表是可变的,元素可以被插入、删除、修改、添加或就地排序。

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

    集合搜集类型,在版本2.4中被增加入语言核心。集合是无索引、无次序的搜集,它包含唯一性的不可变对象作为元素,并且实现了集合论运算,比如并集|、交集&、相对补集-、对称差^,和子集测试<=、真子集测试<、超集测试>=、真超集测试>。有二种类型的集合:可变的set和不可变的frozenset。

    Python允许编程者使用类,定义自己的类型

    ,类是在面向对象编程中最经常使用的。类的新实例,是通过调用这个类的构造器而创建的,而类都是元类type的实例,type是type元类自身的实例,这允许了元编程和反射。在版本3.0之前,Python有两种类:旧式的和新式的。二种样式的语法是一样的,不同在于是否直接或间接的继承自类object,所有新式类都从object继承,并且是type的实例。在Python 2系列2.2以上,二种类都可以使用

    。在Python 3.0中淘汰了旧式类。

    长期规划是支持渐进类型

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


    Python 3内建类型小结

    类型

    可变性

    描述

    语法例子

    bool

    不可变

    布尔值,有表示值False和True的两个对象。作为整数类型numbers.Integral的子类型,它们在几乎所有上下文中,表现得如同0和1,除了在转换成字符串时转换为"False"和"True"之外。

    True
    False

    int

    不可变

    整数,其大小在理论上无限制,实际上受限于内存


    42

    float

    不可变

    双精度浮点数,确切精度依赖于机器。一般实现为IEEE 754标准binary64浮点数,它有53个二进制有效数位精度

    1.414



    complex

    不可变

    复数,即分别表示实部与虚部的两个双精度浮点数的有序对。

    3+2.7j

    range

    不可变

    数的序列,通常用在for循环中指定循环次数


    range(1, 10)
    range(10, -5, -2)



    str

    不可变

    字符串,即Unicode代码点序列。字符串中的代码点都在范围U+0000..U+10FFFF之内。Python没有char类型,这些代码点都表示为长度为1的字符串对象。

    'Wikipedia'"Wikipedia""""Spanningmultiple lines"""

    bytes

    不可变

    字节序列,其项目是8位字节,用范围0 <= x < 256的整数表示。

    b'Some ASCII'
    b"Some ASCII"
    bytes([0x53, 0x74, 0x72])

    bytearray

    可变

    bytearray(b'Some ASCII')
    bytearray(b"Some ASCII")
    bytearray([0x53, 0x74, 0x72])

    list

    可变

    列表,可以包含任意的Python对象。

    [4.0, 'string', True]
    []

    tuple

    不可变

    元组,可以包含任意的Python对象。只有一个项目的元组,可以通过向表达式后缀一个逗号来形成。

    (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

    不可变

    这个类型有一个单一对象作为值,它通过文字...或内建名字Ellipsis来访问,它的真值为真。它用于NumPy多维阵列索引



    ...
    Ellipsis

    types.NoneType

    不可变

    这个类型有叫做None的一个单一对象Null作为值



    ,它被用来指示值的缺席,比如不返回任何东西的函数返回它,它的真值为假。

    None

    types.NotImplementedType

    不可变

    这个类型有一个单一对象NotImplemented作为值。数值方法和细化比较方法,在它们仍未对提供的运算数实现这个运算之时,返回这个值。它不应该在布尔值上下文中求值。

    NotImplemented


    除了各种数据类型,Python解释器还内建了很多其他类型,包括可调用类型:用户定义函数、实例方法、生成器函数、协程函数、异步生成器函数、内建函数、内建方法、类、类方法;模块,定制类,类实例,I/O对象(也叫做文件对象),和暴露给用户的一些内部类型:代码对象、框架对象、溯回对象、切片对象、静态方法对象、类方法对象。


    数学


    Python的算术运算,使用平常的符号+、-、*、/和模除%(这里的余数可以是负数,比如4 % -3 == -2)。它还有下取整除法算符//,指数算符**,比如5**3 == 125及9**0.5 == 3.0,和矩阵乘法算符@

    。这些算符就像在传统数学中一样运算,具有同样的优先级规则,中缀算符+、-,还可以分别表示取原数和取相反数的一元算符。

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

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

    Python允许由比较运算链接起来的布尔表达式,表现得如在数学中常用的一样。比如表达式a < b < c,测试a < b and b < c

    。C语言将它解析为(a < b) < c:即首先求值a < b,其结果为0或1,接着把这个结果比较于c

    Python对所有整数运算,使用任意精度算术。在decimal模块中的Decimal类

    ,提供十进制浮点数,具有用户可按需要而更改的缺省28个十进制有效数位精度,并有多种修约方式。在fractions模块中的Fraction类,提供任意精度的有理数

    由于Python有着广泛的数学库,除了求绝对值函数abs()列入内建函数之外,大多数数学函数,处于math和cmath模块内。前者用于实数运算,而后者用于复数运算。

    特别是第三方库NumPy,进一步扩展了固有能力,Python经常被用作科学脚本语言,来处理如数值数据处理和操纵等问题


    标准库


    Python拥有一个强大的标准库

    。Python标准库包括了如下功能:


    • 内建函数
    • 内建常量
    • 内建类型
    • 内建异常
    • Python运行时服务
    • 定制Python解释器
    • 导入模块
    • Python语言服务
    • 文本处理服务
    • 二进制数据服务
    • 数据类型
    • 数值和数学模块
    • 函数式编程模块
    • 文件和目录访问
    • 数据持久化
    • 数据压缩和存档
    • 文件格式
    • 加密服务
    • 通用操作系统服务
    • MS Windows专有服务
    • Unix专有服务
    • 并发执行
    • 网络和进程间通信
    • 互联网数据处理
    • 结构式标记处理工具
    • 互联网协议及其支持
    • 多媒体服务
    • 国际化
    • 程序框架
    • Tk图形用户界面
    • 开发工具
    • 调试和分析
    • 软件打包和发布



    程序代码实例


    一个在标准输出设备上输出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 = 1for i in range(2, n + 1):    fact *= iprint(fact)


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


    实现


    Python是一门跨平台的脚本语言,Python规定了一个Python语法规则,根据该规则可编写Python解释器

    。Python属于动态语言,将Python程序编译成中间形式的字节码,并接着在它的虚拟机上执行,相较于C/C++和java的等编译语言而言运行速度较慢


    活跃开发的实现


    • CPython:官方的解释器,需要区别于其他解释器的时候才以CPython称呼,若无特别说明,一般Python指此解释器实现。
    • PyPy:用RPython书写的Python实现,兼容至CPython 3.8和3.9,它采用了跟踪JIT,缺省支持stackless模态。
    • MicroPython:为微控制器而优化的Python 3变体,它实现了完整的Python 3.4语法,和补充自版本3.5的async/await关键字,和后来版本的一些选定特征;它提供了实现Python标准库模块功能子集的内建模块,和特定于微控制器的一些模块。CircuitPython是Adafruit开发的MicroPython分叉。
    • Pyston:CPython 3.8.12的分叉,具有包括JIT的性能优化

    。其JIT部分,单独发行为扩展模块pyston_lite_autoload,它支持Python3.7—3.10


  • Cinder:由Meta开源发布,它是Meta内部使用的面向性能的CPython 3.10分叉,具有包括JIT的很多优化

  • Codon:将Python代码编译成本机机器代码的高性能Python编译器,不带有任何运行时开销,支持本机多线程
  • ,它由MIT CSAIL的研究人员开发



    到其他语言的交叉编译器


    • Cython:将扩充了静态类型的Python超集编译成C语言或C++。
    • Numba:使用LLVM,将包括很多NumPy函数的聚焦数值计算的Python子集,翻译成快速的机器码,它为在CPU和GPU上并行化Python代码提供了大量选项。
    • Pyjion:CPython的JIT扩展,它将Python代码编译成本机CIL,从而使用.NET 7的CoreCLR来执行它

  • Nuitka:用Python书写的到C11或C++03的优化编译器,它能建立不需单独的安装器就能运行的可执行程序

  • Pythran:将聚焦于科学计算的Python子集编译成C++11的提前编译器,它能利用上多核和SIMD指令单元

  • Brython:运行在浏览器中的Python 3实现,具有到DOM元素和事件的接口

  • MyHDL:将Python编译成Verilog或VHDL



    仍在维护中的旧版本实现有:Stackless Python,它是实现微线程的CPython 3.8分叉;IronPython,它是面向.NET和Ecma CLI的Python 2.7和Python 3.4实现;Jython,它是用Java实现的Python 2.7。


    开发环境


    通用文本编辑器


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


    • Visual Studio Code
    • Atom
    • Eclipse
    • emacs
    • 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。它是商业软件,但也具有社区版和教育版。
    • Thonny:适用于编程初学者的IDE。
    • Wing IDE:商业软件,有免费的功能有限的Wing 101。



    应用


    Python Powered


    主条目:Python软件列表


    在很多操作系统里,Python是标准的系统组件,它被列入Linux标准规范之中

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

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

    Python包索引是公开的软件包在线仓库。pip是官网推荐的以安全方式安装Python应用及其依赖软件包的最流行工具

    。要安装在整个操作系统范围内共享的Python包,现在需要通过操作系统的软件包管理系统。要将特定于应用的依赖包隔离于共享的Python安装可以使用venv或virtualenv。pipx可以将Python应用安装于隔离的环境中并在其中运行它。pipenv能自动为用户项目建立和管理虚拟环境,并在安装/卸装软件包的时候,向此项目的Pipfile文件增加/移除这个软件包

    自从2003年,Python始终排行于TIOBE编程社区索引前十最流行编程语言,在2021年10月它首次达到了第一名最流行语言(居于C和Java之前)

    ,并被选为2007年、2010年、2018年、2020年和2021年的年度编程语言


    网络服务


    参见:Web服务


    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框架,聚焦于快速开发,偏好约定优于配置方式。

  • Pyramid:极简主义的Web框架,不预定持久化方式,它是Pylons计划的一部分。

  • Flask:微Web框架,不要求特定的工具或库。

  • Twisted:事件驱动的网络编程框架。它支持多数标准的网络协议(包含客户端和服务器),并且提供了多种工具,适用于编写高性能的服务器软件。

  • Requests:适合于常人使用的HTTP库,封装了许多繁琐的HTTP功能,极大地简化了HTTP请求所需要的代码量。

  • Beautiful Soup:用来解析HTML/XML的一个简单易用Python包。

  • uvloop:是对内建asyncio事件循环的快速的、直截了当的替代者
  • ,它用Cython实现并在底层使用了libuv。

  • aiohttp:基于asyncio的HTTP客户端和服务器二者



    图形用户界面


    参见:GUI


    Python本身包含了Tkinter库,它是Python的业界标准GUI并被集成进入了IDLE。Tkinter基于了Tcl命令工具,能够支持简单的GUI开发。但是为了让所开发的软件运行速度更快,并与用户的桌面环境更契合,人们一般会选择采用第三方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应用

  • Dear PyGui:快速而强力的具有极小依赖性的GUI工具箱

  • pywebview:轻量级跨平台的对WebView构件的包装器,允许在其本地GUI窗口中显示HTML内容



    数据科学


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


    • NumPy:Python的基础性的科学计算软件库,提供了矩阵、线性代数、傅立叶变换等的解决方案。
    • SciPy:用Python实现了MATLAB所有功能的软件库,使用NumPy的多维阵列作为基本数据结构。
    • CuPy:NumPy/SciPy兼容的GPU加速的阵列库
  • ,它可在NVIDIA CUDA或AMD ROCm平台上充当其直截了当的替代者,来运行现存的NumPy/SciPy代码。

  • pandas:用于数据分析和数据操纵的软件库,建造在NumPy基础上,提供了类似于R语言中同名对象的加标签数据结构“数据帧”
  • ,和统计函数等。

  • PyMC:基于Theano的概率编程库,用于贝叶斯统计建模和概率机器学习。

  • Dask:伸缩范围从笔记本电脑至计算机集群的并行计算库
  • ,它由两部分构成:为计算而优化的动态任务调度,和“大数据”搜集如并行的阵列、数据帧和列表。这些搜集将常用接口如NumPy、pandas或Python迭代器,扩展到大过内存或分布式的环境,并行的搜集运行在动态任务调度器顶上。

  • matplotlib:用于Python和NumPy的绘图库,实现类似MATLAB的绘图功能。

  • Dash:基于React、Flask和Plotly公司的Plotly.js
  • 之上的框架,它将现代用户界面元素如下拉选单、滑动条和图形,直接链接至分析型Python代码。它和Streamlit、Panel和Voilà,是被称为“仪表板”的数据可视化工具



    重要的人工智能机器学习框架有:


    • scikit-learn:基于NumPy、SciPy、Joblib

    和threadpoolctl

  • 的机器学习软件库,实现许多知名的机器学习算法,其绘图功能依赖于matplotlib。

  • 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之上。



    其它种类的库


    • pegen:Python的PEG解析器生成器

  • PeachPy:采用高层Python的可移植高效x86-64汇编代码生成器

  • SymPy:支持数学符号运算如微积分等的软件库,用于提供计算机代数系统。

  • SQLAlchemy:针对关系型数据库的对象关系映射(ORM)工具。

  • 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风格访问


  • Kompute:通用Vulkan计算框架,针对C++和Python

  • SimPy:基于由Python生成器函数定义的进程的离散事件模拟框架

  • Pillow:是基于Python的图像处理库
  • ,它支持广泛的图形文件格式,分叉于已终止的PIL。

  • Kornia:基于PyTorch的可微分计算机视觉库

  • pygame:开发视频游戏的Python软件库,基于了SDL库

  • pyglet:Python编写的面向对象的游戏和多媒体库,利用了FFmpeg库。

  • pypdf:能够分割、合并、修剪和转变PDF文件的Python库
  • 。创建PDF文件可以采用reportlab


  • python-docx:创建和修改Microsoft Word的docx文档的Python库

  • pythonnet:针对.NET的程序包
  • ,它可以近乎无缝的集成.NET通用语言运行库(CLR)。

  • Fabric:经由SSH远程执行shell命令的高层库
  • ,它产生有用的Python对象作为回馈。

  • Prefect:现代工作流程编排框架
  • ,它易于建造、调度和监控健壮的数据流水线。

  • Panda3D:开源游戏引擎,包括了图形、音频、I/O、碰撞侦测和其他与3D游戏有关的功能,使用Python作为游戏开发语言

  • PyInstaller:将Python应用和它的依赖项捆绑成一个单一的包
    • ,从而不需要安装Python解释器或任何模块就可以运行应用。



    应用软件


    一些Linux发行版,使用Python语言编写安装器,比如Ubuntu的Ubiquity和Fedora的Anaconda;或使用它编写软件包管理系统,比如Gentoo的Portage。一些著名的互联网公司在内部使用Python

    。一些游戏比如EVE,使用Python编写游戏的逻辑、服务器。如下著名应用使用Python编写或将它作为嵌入式脚本:


    • IPython:以多种编程语言进行交互式计算的命令shell和Jupyter的内核,最初为Python开发,它提供了内省、富媒体、shell语法、tab补全和历史。
    • Conda:跨平台的、语言无关的二进制包管理器,它被Anaconda发行采用。
    • SCons:软件建造工具,它可代替make构建编译程序。
    • Gunicorn:使用Python语言编写的WSGI Web服务器。
    • Plone:基于Zope的内容管理系统。
    • Mezzanine:基于Django框架的内容管理系统。
    • Orange:卢布尔雅那大学开发的开源机器学习和数据可视化软件,利用了PyQt5和基于Blink的PyQtWebEngine,通过广大多样的工具箱来建造数据分析工作流程

  • SageMath:覆盖许多数学功能的应用软件。

  • Veusz:用Python、PyQt和NumPy写成的科学绘图软件,可生成出版水准的PDF或SVG输出。

  • unoconv:在LibreOffice/OpenOffice所支持格式之间的通用文档转换器
    • Blender:开源3D绘图软件,使用Python作为建模工具与GUI语言。
    • Inkscape:开源的SVG矢量图形编辑器,使用Python用于插件。
    • Pitivi:用Python开发的基于GStreamer的视频编辑软件。



    社群流行


    • 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一样可用于通用编程”


    代码示例



  • 缩进示例: def is_even(a: int) -> bool: """确定数a是否是偶数.""" if a % 2 == 0: print('偶数!') return True print('奇数!') return False # 参数比后续部份多一层缩进 def long_function_name( var_one, var_two, var_three, var_four): # 可选的圆括号内后续行多一层缩进 if (this_is_first_thing and that_is_second_thing): do_something() # 可选的圆括号内后续行不额外缩进 elif (this_is_third_thing and that_is_fourth_thing): do_something_different() # 参数相对行首缩进一层 spam = long_function_name( arg_one, arg_two, arg_three, arg_four) # 参数按开括号界定垂直对齐 eggs = long_function_name(arg_one, arg_two, arg_three, arg_four) # 可选的闭括号位置 my_list = [ 1, 2, 3, 4, 5, 6, ] # 可选的闭括号位置 my_set = { 1, 2, 3, 4, 5, 6, }


  • 采用了并行赋值的斐波那契数列函数示例: def fib(n): # 写出从第0项到第n项的Fibonacci系列 a, b, i = 0, 1, 0 while i <= n: print(a, end=' ') a, b, i = b, a+b, i+1 print()


  • 产生素数的惰性生成器的示例:

    from itertools import countdef generate_primes(stop_at=0):    if stop_at != 1:        primes = [2]        yield 2    for n in count(3, 2):        if 0 < stop_at < n:            return # 引发StopIteration异常        composite = False        for p in primes:            if not n % p:                composite = True                break            elif p ** 2 > n:                break        if not composite:            primes.append(n)            yield n


  • 上述函数的隐式迭代用例:

  • for i in generate_primes():  # 迭代于100以内所有素数上    if i > 100:        break    print(i)


  • 在生成器表达式中使用上述函数,定义了一个惰性的、巨大而并非无限的搜集的示例:

  • from itertools import isliceprimes_under_million = (i for i in generate_primes() if i < 1000000)two_thousandth_prime = islice(primes_under_million, 1999, 2000) print(next(two_thousandth_prime))




  • 用生成器模拟协程示例: def produce(n): try: for item in range(n): print('producing item {} ->'.format(item)) yield item except GeneratorExit: return def consume(): item = None try: while True: item = yield item print('consuming item {} <-'.format(item)) except GeneratorExit: return t1 = produce(10) t2 = consume() next(t2) r = [] try: while True: p = next(t1) r += [t2.send(p)] except StopIteration: t2.close()


  • 遵循EAFP(请求原谅比获得许可更容易)风格的异常处理示例: f = None try: f = open("aFileName", mode="w") f.write(could_make_error()) # 不存在could_make_error()则产生错误 except IOError as error: print(error) print("不能打开文件") except: # 捕获所有异常 print("未预期的错误") else: # 在没有出现异常时执行 print("文件写入完全成功") finally: # 清除行动,总是执行 if f: f.close()


  • 使用with将文件作为资源来管理的示例: from contextlib import contextmanager @contextmanager def opened(filename, mode="r"): try: f = open(filename, mode) except IOError as error: print(error) yield None else: try: yield f finally: f.close() with opened("aFileName", mode="w") as f: try: f.write(could_make_error()) # 不存在could_make_error()则产生错误 except AttributeError: print("不能打开文件") except: # 捕获所有异常 print("未预期的错误") else: # 在没有出现异常时执行 print("文件写入完全成功")


  • 本地的协程示例: import asyncio import random async def produce(queue, n): for item in range(n): # 生产一个项目,使用sleep模拟I/O操作 print('producing item {} ->'.format(item)) await asyncio.sleep(random.random()) # 将项目放入队列 await queue.put(item) # 指示生产完毕 await queue.put(None) async def consume(queue): while True: # 等待来自生产者的项目 item = await queue.get() if item is None: break # 消费这个项目,使用sleep模拟I/O操作 print('consuming item {} <-'.format(item)) await asyncio.sleep(random.random()) async def main(): queue = asyncio.Queue() task1 = asyncio.create_task(produce(queue, 10)) task2 = asyncio.create_task(consume(queue)) await task1 await task2 asyncio.run(main())


  • 局部变量示例: >>> def spam(): ... print(b) ... >>> b=10 >>> spam() 10 >>> def spam(): ... print(b) ... b=100 ... >>> b=10 >>> spam() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in spam UnboundLocalError: local variable 'b' referenced before assignment


  • 全局变量示例: >>> def spam(): ... print(b) ... global b ... b=100 ... File "<stdin>", line 3 SyntaxError: name 'b' is used prior to global declaration >>> def spam(): ... global b ... print(b) ... b=100 ... >>> b=10 >>> spam() 10 >>> b 100


  • 非局部变量示例: >>> def spam(): ... def eggs(): ... global b ... print(b) ... b=1000 ... b=100 # 对eggs()而言是非局部变量 ... eggs() ... >>> b=10 >>> spam() 10 >>> b 1000 >>> def spam(): ... def eggs(): ... nonlocal b ... b=1000 ... b=100 # 对eggs()而言是非局部变量 ... eggs() ... print(b) ... >>> b=10 >>> spam() 1000 >>> b 10


  • 序列解包、可迭代解包和字典解包示例: >>> a = [1, 2, 3]; b = [4, 5] >>> i, j, k = a >>> print(i, j, k) 1 2 3 >>> c = [*a, b] >>> c [1, 2, 3, [4, 5]] >>> d = {*a, *b} >>> d {1, 2, 3, 4, 5} >>> e = (*a, *b) >>> e (1, 2, 3, 4, 5) >>> f = {'as':1, 'bs':2 }; g = {'cs':3, 'ds':4} >>> h = {**f, **g} >>> h {'as': 1, 'bs': 2, 'cs': 3, 'ds': 4}


  • 列表的推导式示例。比如:

    >>> [x + 3 for x in range(4)][3, 4, 5, 6]


  • 快速排序算法可以优雅的(尽管不高效的)使用列表推导式表达为:

  • def qsort(L):    if L == []:        return []    pivot = L[0]    return (qsort([x for x in L[1:] if x < pivot]) +            [pivot] +            qsort([x for x in L[1:] if x >= pivot]))




  • 生成器表达式示例。比如: >>> sum(x * x for x in range(10)) 285 >>> dict((n, n*n) for n in range(5)) {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} >>> set(n*n for n in range(5)) {0, 1, 4, 9, 16}


  • 字典推导式{expr1: expr2 for k, v in d},等价于:

    result={}for k, v in d.items():    result[expr1]=expr2return result


    >>> {x: x + 3 for x in range(4)}{0: 3, 1: 4, 2: 5, 3: 6}


  • 集合推导式{expr1 for x in stuff},等价于:

  • result = set()for x in stuff:    result.add(expr1)return result


    >>> {x + 3 for x in range(4)}{3, 4, 5, 6}




  • 下面几个判断语句为真,表示列表分片结果符合预期: >>> nums = [1, 3, 5, 7, 8, 13, 20] >>> nums[2:5] == [5, 7, 8] #从下标为2的元素切割到下标为5的元素,但不包含下标为5的元素。 True >>> nums[1:] == [3, 5, 7, 8, 13, 20] #切割到最后一个元素。 True >>> nums[:-3] == [1, 3, 5, 7] #从最开始的元素一直切割到倒数第3个元素。 True >>> nums[:] == [1, 3, 5, 7, 8, 13, 20] #返回所有元素。改变新的列表不会影响到nums。 True >>> nums[1:5:2] == [3, 7] #从下标为1的元素切割到下标为5的元素,但不包含下标为5的元素,且步长为2。 True


  • 匿名函数示例:

    >>> from functools import reduce>>> reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) 15>>> fac = lambda n: (1 if n<2 else n*fac(n-1))>>> fac(5)120>>> [*map(fac, [1, 2, 3, 4, 5])][1, 2, 6, 24, 120]


  • 不动点组合子示例:

  • >>> Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))>>> fac = lambda f: lambda n: (1 if n<2 else n*f(n-1))>>> Y(fac)(5)120>>> fib = lambda f: lambda n: 0 if n == 0 else (1 if n == 1 else f(n-1) + f(n-2))>>> Y(fib)(6)8>>> [*map((lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args))))(lambda f: lambda n: (1 if n<2 else n*f(n-1))), [1, 2, 3, 4, 5])][1, 2, 6, 24, 120]


  • 上述Y组合子代码源出自Rosetta Code. [2020-10-21]. (原始内容存档于2021-01-11).其原理可参见Equational derivations of the Y combinator and Church encodings in Python. [2020-10-21]. (原始内容存档于2020-11-12).



  • 多行字符串文字带有字符串插值(使用了format方法)的示例: print("""亲爱的{recipient}, 我希望你离开Sunnydale并永不返回. 不是很爱你的, {sender} """.format(sender="吸血鬼猎人Buffy", recipient="Spike"))


  • 原始字符串的示例: >>> # Windows路径,即使是原始字符串也不能结束于反斜杠 >>> r"C:\Spam\Eggs\Ham\" File "<stdin>", line 1 r"C:\Spam\Eggs\Ham\" ^ SyntaxError: EOL while scanning string literal >>> dos_path = r"C:\Spam\Eggs\Ham\ " # 通过增加尾随的空格 >>> dos_path.rstrip() # 并接着移除它来避免错误 'C:\Spam\Eggs\Ham\' >>> quoted_dos_path = r'"{}"'.format(dos_path) >>> quoted_dos_path '"C:\Spam\Eggs\Ham\ "' >>> # 匹配具有可能的反斜杠引述的引述字符串的正则表达式 >>> import re >>> re.match(r'"(([^"\]|\.)*)"', quoted_dos_path).group(1).rstrip() 'C:\Spam\Eggs\Ham\' >>> code = 'spam(2, eggs)' >>> # 反转有二个参数的函数调用的两个实际参数 >>> re.sub(r'\(([^,]*),\s*([^,]*)\)', r'(, )', code) 'spam(eggs, 2)' >>> # 注意如果实际参数中有圆括号或逗号则上例无效。


  • 字符串文字符串接示例: >>> print("hello " 'world') hello world >>> str1="hello "; str2='world' >>> print(str1 + str2) hello world


  • 格式化字符串的示例,例如下列命令行echo命令:

    num="3"; printer="HP Laserjet"echo "I just printed ${num} pages to the printer ${printer}"


  • 等价于如下Python中的任何一种print函数调用:

  • num = 3; printer="HP Laserjet"print(f"I just printed {num} pages to the printer {printer}")print("I just printed {} pages to the printer {}".format(num, printer))print("I just printed {0} pages to the printer 学习编程语言".format(num, printer))print("I just printed {num} pages to the printer {printer}".format(num=num, printer=printer))print("I just printed %s pages to the printer %s" % (num, printer))print("I just printed %(num)s pages to the printer %(printer)s" % {"num": num, "printer": printer})




  • 词法闭包的例子: def f(x): def g(y): return x + y return g # 返回一个闭包。 h = lambda x: lambda y: x + y # 将指定闭包赋值给变量。 a = f(1) b = h(1) c = f(2) # 使用存储在变量中的闭包。 assert a(5) == 6 assert b(5) == 6 assert c(5) == 7 # 使用闭包而不事先把它们绑定到变量。 assert f(1)(5) == 6 # f(1)是个闭包。 assert h(1)(5) == 6 # h(1)是个闭包。 assert f(2)(5) == 7 # f(2)是个闭包。


  • 函数的形式参数缺省值的持久性示例: >>> def f(a, L=[]): ... L.append(a) ... return L ... >>> print(f(1)) [1] >>> print(f(2)) [1, 2] >>> print(f(3)) [1, 2, 3]


  • 函数的形实参数二者结合示例。例如: >>> def spam(a): ... a.append('LovelySpam') ... >>> def eggs(b): ... b=100 #实际上是重新绑定了另一个整型对象100 ... >>> a=[] >>> b=10 >>> spam(a) >>> eggs(b) >>> print(a) ['LovelySpam'] >>> print(b) 10


  • 函数的形式参数缺省值的定义示例: >>> from inspect import getfullargspec >>> def func(p1, /, p2, p3="x", *, p4): pass ... >>> getfullargspec(func) FullArgSpec(args=['p1', 'p2', 'p3'], varargs=None, varkw=None, defaults=('x',), kwonlyargs=['p4'], kwonlydefaults=None, annotations={})


  • 函数的可变参数的定义示例: >>> from inspect import getfullargspec >>> def func(p1, /, p2, *args, p3, **kwargs): pass ... >>> getfullargspec(func) FullArgSpec(args=['p1', 'p2'], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=['p3'], kwonlydefaults=None, annotations={})


  • 定义修饰器的示例:

    def viking_chorus(myfunc):    def inner_func(*args, **kwargs):        for i in range(3):            myfunc(*args, **kwargs)    return inner_func


  • 调用修饰器的示例:

  • @viking_chorus    def menu_item(*args):    print(", ".join(args)+", and spam")


  • 等价于:

  • def menu_item(*args):    print(", ".join(args)+", and spam")menu_item = viking_chorus(menu_item)


  • viking_chorus修饰后的menu_item将原来定义运行3次:

  • >>> menu_item("egg","bacon")egg, bacon, and spamegg, bacon, and spamegg, bacon, and spam




  • 修饰器工厂示例,这里的favourite_colour接受一个实际参数,并返回一个修饰器:

    def favourite_colour(colour):    def decorator(func):        def wrapper(*args, **kwargs):            print(f"My favourite colour is {colour}.")            func(*args, **kwargs)        return wrapper    return decoratordef invincible(func):    def wrapper(*args, **kwargs):        print("I'm invincible!")        func(*args, **kwargs)    return wrapper


  • 使用毗连的修饰符链接修饰器示例:

  • @invincible@favourite_colour("blue")def black_knight():    print("None shall pass.")


  • 使用中间变量链接修饰器示例:

  • blue_decorator = favourite_colour("blue")decorated_by_blue = blue_decorator(black_knight)black_knight = invincible(decorated_by_blue)


  • 它们等价于:

  • black_knight = invincible(favourite_colour("blue")(black_knight))


  • black_knight()结果为:

  • >>> black_knight()I'm invincible!My favourite colour is blue.None shall pass.




  • 调用函数使用帮助信息示例。比如: >>> def randint(a, b): ... "Return random integer in range [a, b], including both end points." ... >>> help(randint) Help on function randint in module __main__: randint(a, b) Return random integer in range [a, b], including both end points.


  • 如下这样给参数增加类型标注的提示信息: >>> def greeting(name: str) -> str: ... return 'Hello ' + name ... >>> greeting.__annotations__ {'name': <class 'str'>, 'return': <class 'str'>}


  • 对象的方法示例: >>> class Fish(object): ... hungry = True ... def eat(self, food): ... if food is not None: ... self.hungry=False ... >>> def status(self): ... print("Hungray!" if self.hungry else "Not hungray!") ... >>> e = Fish() >>> status(e) Hungray! >>> Fish.hungry = False >>> from types import MethodType >>> e.status = MethodType(status, e) >>> e.status() Not hungray! >>> Fish.hungry = True >>> Fish.status = status >>> f = Fish() >>> Fish.status(f) Hungray! >>> f.eat("earthworm") >>> f.status() Not hungray!


  • 特殊方法和子类调用超类方法的例子: >>> class Thought(object): ... cls_name = "类型Thought" ... def __init_subclass__(cls): ... cls.cls_name = "类型Thought的子类型" ... def __init__(self, *args, **kwargs): ... print(f"我是{type(self).cls_name}的新对象!") ... if len(args) != 0 or len(kwargs) !=0: ... print(f"init: nargs={len(args)}, nkwargs={len(kwargs)}") ... self.notion = "我觉得我在平行宇宙中把车停歪了." ... def message(self, *args): ... print(self.notion) ... if len(args) != 0: ... print("\n".join(args)) ... >>> class Advice(Thought): ... def message(self): ... super(Advice, self).message("警告: 日历里的日期比它们看起来更近!") ... >>> t = Thought() 我是类型Thought的新对象! >>> t.message() 我觉得我在平行宇宙中把车停歪了. >>> a = Advice() 我是类型Thought的子类型的新对象! >>> a.message() 我觉得我在平行宇宙中把车停歪了. 警告: 日历里的日期比它们看起来更近! >>> # 内省一下: >>> [*super.__dict__] ['__repr__', '__getattribute__', '__get__', '__init__', '__new__', '__thisclass__', '__self__', '__self_class__', '__doc__'] >>> [*super(Advice).__thisclass__.__dict__] ['__module__', 'message', '__doc__', 'cls_name'] >>> super(Advice).__thisclass__.__dict__['cls_name'] '类型Thought的子类型' >>> [*super(Advice, a).__self__.__dict__] ['notion'] >>> super(Advice, a).__self_class__.__dict__['cls_name'] '类型Thought的子类型' >>> super(Advice, a).message() 我觉得我在平行宇宙中把车停歪了. >>> super(Advice).__get__(a).message() 我觉得我在平行宇宙中把车停歪了.


  • 在类中采用数据描述器的示例: >>> class RevealAccess: ... """正常的设置和返回值的数据描述器, ... 它还打印记录这次访问的一个消息。 ... """ ... def __init__(self, initval=None, name='var'): ... self.val = initval ... self.name = name ... def __get__(self, obj, objtype): ... print('Retrieving', self.name) ... return self.val ... def __set__(self, obj, val): ... print('Updating', self.name) ... self.val = val ... >>> class MyClass: ... x = RevealAccess(10, 'var "x"') ... y = 5 ... >>> m = MyClass() >>> m.x Retrieving var "x" 10 >>> vars(m) {} >>> MyClass.__dict__['x'].val 10 >>> m.x = 20 Updating var "x" >>> vars(m) {} >>> MyClass.__dict__['x'].val 20 >>> m.y 5 >>> vars(m) {} >>> m.y = 5 >>> vars(m) {'y': 5}


  • 特殊方法、类方法和静态方法(__new__())示例: >>> from weakref import WeakValueDictionary >>> class D: ... _template = {} ... _obj_dict = WeakValueDictionary() ... def __new__(cls, *args, **kwargs): ... obj = super(D, cls).__new__(cls) ... cls._obj_dict[id(obj)] = obj ... return obj ... @classmethod ... def load(cls, dict): ... cls._template.update(dict) ... @classmethod ... def create(cls, *args, **kwargs): ... return cls(cls._template, *args, **kwargs) ... @classmethod ... def count(cls): ... return len(cls._obj_dict) ... def __init__(self, dict={}, /, *args, **kwargs): ... self.__dict__.update(dict) ... self.__dict__.update(kwargs) ... def __call__(self, *args, **kwargs): ... self.__dict__.update(kwargs) ... return self.__dict__.copy() ... def __len__(self): ... return len(self.__dict__) ... def __getitem__(self, key): ... return self.__dict__[key] ... def __setitem__(self, key, value): ... self.__dict__[key] = value ... >>> a = {'ak': 1, 'bk': 2, 'ck': 3} >>> d = D(a, dk=4) >>> d() {'ak': 1, 'bk': 2, 'ck': 3, 'dk': 4} >>> D.load(a) >>> e = D.create(ck=4) >>> e() {'ak': 1, 'bk': 2, 'ck': 4} >>> f = D(ak=1, bk=2) >>> f(ck=3) {'ak': 1, 'bk': 2, 'ck': 3} >>> f['ak'] 1 >>> f['ak'] = 5 >>> f() {'ak': 5, 'bk': 2, 'ck': 3} >>> len(f) 3 >>> D.count() 3 >>> del f >>> D.count() 2 >>> d.__weakref__ in D._obj_dict.valuerefs() True


  • 在类中调用property()的例子:

    >>> class C:...     def __init__(self):...         self.__x = None...     def getx(self):...         return self.__x...     def setx(self, value):...         self.__x = value...     def delx(self):...         del self.__x...     x = property(getx, setx, delx, "I'm the 'x' property.")... >>> c = C()>>> vars(c){'_C__x': None}>>> {*C.__dict__}{'__init__', 'setx', '__weakref__', 'delx', 'x', 'getx', '__doc__', '__module__', '__dict__'}


  • 上述代码可以采用修饰符进一步的书写为:

  • >>> class C:...     def __init__(self):...         self.__x = None...     @property...     def x(self):...         """I'm the 'x' property."""...         return self.__x...     @x.setter...     def x(self, value):...         self.__x = value...     @x.deleter...     def x(self):...         del self.__x... >>> c = C()>>> vars(c){'_C__x': None}>>> {*C.__dict__}{'__init__', '__weakref__', 'x', '__doc__', '__module__', '__dict__'}




  • 建立列表的特殊语法示例:

    a_list = [1, 2, 3, 'a dog']


  • 采用正常的对象创建方式的示例:

  • a_second_list = list()a_second_list.append(4)a_second_list.append(5)


  • 建立元组的特殊语法示例:

  • a_tuple = 1, 2, 3, 'four'


  • 建立集合的特殊语法示例:

  • some_set = {0, (), False}


  • 建立字典的特殊语法示例:

  • a_dictionary = {'key 1': 'value 1', 2: 3, 4: []}




  • 两个类及元类等的实例关系(蓝色连接)与继承关系(绿色连接)示意图:




  • r = objectc = typeclass M(c): passclass A(metaclass=M): passclass B(A): passb = B()






  • >>> type(b)<class '__main__.B'>>>> print(type(B), B.__bases__)<class '__main__.M'> (<class '__main__.A'>,)>>> print(type(A), A.__bases__)<class '__main__.M'> (<class 'object'>,)>>> print(type(M), M.__bases__)<class 'type'> (<class 'type'>,)>>> print(type(c), c.__bases__)<class 'type'> (<class 'object'>,)>>> print(type(r), r.__bases__)<class 'type'> ()




  • 数学运算示例。比如:

    >>> def mean(seq):...     return sum(seq) / len(seq)... >>> mean([3, 4])3.5>>> import math>>> print(math.sin(math.pi/2))1.0