4.4.2 复合语句:
- 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语句导致相应的名字,提及在最近包围函数作用域内的先前绑定变量(即非局部变量)。
4.5 表达式
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为构造列表、字典或集合,提供了叫做“显示”的特殊语法,它们每个都有两种方式:包容内容要么显式列举出来;要么通过一组循环和过滤指令计算而来,这叫做“推导式”。列表显示是包围在方括号中的可以为空的一系列表达式,一个例子列表可写为。字典显示是包围在花括号中的可能为空的一系列的键/数据项对。集合显示用花括号来指示,与字典显示的区别是缺少分隔键与值的分号。自从Python 3.5,增加了在表达式列表中的“可迭代解包”*,和在字典显示中的“字典解包”**。
-
**Python支持列表推导式。**Python 2.4将列表推导式扩展至更一般性的生成器表达式。Python 3.0又增补了字典推导式和集合推导式。
-
**在Python中,加圆括号形式(parenthesized form),是包围在圆括号中的一个可选表达式列表。**加圆括号的表达式列表产生的东西,就是这个表达式列表所产生的:如果这个列表包含至少一个逗号,它产生一个元组;否则它产生构成这个表达式列表的那个单一表达式。一个例子元组可写为(1,2,3)。元组不是圆括号形成的,而是使用逗号形成的,在没有歧义的情况下,元组的圆括号是可选的。空的圆括号对产生空元组对象。使用序列串接算符+来串接二个元组,产生包含给定元组二者的元素的一个新元组。
-
Python支持在序列对象(比如字符串、元组或列表)上的下标(subscription)表达式:a[索引],和分片表达式:a[开始:停止]或a[开始:停止:步长]。下标索引是基于零的,负数是相对于结尾的。分片范围自从“开始”索引,直到但不包括“停止”索引。分片的第三个参数叫做“步长”(step)或“间隔”(stride),允许元素被跳过和用负数指示反向。分片索引可以省略,例如a[:],这返回整个列表的一个复本。[o]分片的每个元素都是浅层复制的。
-
Python的条件表达式表示为x if c else y。意思是当c为真时,表达式的值为x,否则表达式的值为y。 在运算数的次序上不同于很多其他语言中常见的c ? x : y。
-
Python的匿名函数实现为lambda表达式。匿名函数体只能是一个表达式。
-
自从Python 3.8,介入了赋值表达式,其记号是:=。它将一个表达式赋值给一个标识符,同时还返回这个表达式的值。赋值表达式在用作子表达式,即位于分片表达式、条件表达式、lambda表达式、关键字参数中的表达式和推导式中的if表达式之中,以及在assert和with语句之中的时候,必须围绕着圆括号。在它们可以使用的所有其他地方,包括在if和while语句之中,都不要求圆括号。