1 再谈 print 和 import
虽然print现在实际上是一个函数,但以前却是一种语句
1.1 打印多个参数
你知道,print可用于打印一个表达式,这个表达式要么是字符串,要么将自动转换为字符串。但实际上,你可同时打印多个表达式,条件 是用逗号分隔它们:如果需要,可自定义分隔符:你还可自定义结束字符串,以替换默认的换行符。例如,如果将结束字符串指定为空字符串,以后就可继续打印到当前行。
1.2 导入时重命名
从模块导入时,通常使用import somemodule 或使用from somemodule import somefunction
或from somemodule import somefunction, anotherfunction, yetanotherfunction 或from somemodule import *
仅当你确定要导入模块中的一切时,采用使用最后一种方式。但如果有两个模块,它们都包含函数open,该如何办呢?
有一种办法:在语句末尾添加as子句并指定别名。下面是一个导入整个模块并给它指定别名的例子:导入特定函数并给它指定别名的例子:
2 赋值魔法
2.1 序列解包
赋值语句你见过很多,有的给变量赋值,还有的给数据结构的一部分(如列表中的元素和切片,或者字典项)赋值,但还有其他类型的赋值语句。例如,可同时(并行)给多个变量赋值:
使用这种方式还可交换多个变量的值。
实际上,这里执行的操作称为序列解包(或可迭代对象解包):将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中。
这在使用返回元组(或其他序列或可迭代对象)的函数或方法时很有用。假设要从字典中随便获取(或删除)一个键值对,可使用方法popitem,它随便获取一个键值对并以元组的方式返回。接下来,可直接将返回的元组解包到两个变量中。
这让函数能够返回被打包成元组的多个值,然后通过一条赋值语句轻松地访问这些值。要解包的序列包含的元素个数必须与你在等号左边列出的目标个数相同,否则Python将引发异常。
可使用星号运算符(*)来收集多余的值,这样无需确保值和变量的个数相同,如下例所示:
赋值语句的右边可以是任何类型的序列,但带星号的变量最终包含的总是一个列表。在变量和值的个数相同时亦如此
2.2 链式赋值
链式赋值是一种快捷方式,用于将多个变量关联到同一个值。这有点像前一节介绍的并行赋值,但只涉及一个值:
2.3 增强赋值
可以不编写代码x = x + 1,而将右边表达式中的运算符(这里是+)移到赋值运算符(=)的前面,从而写成x += 1。这称为增强赋值,适用于所有标准运算符,如*、/、%等
增强赋值也可用于其他数据类型(只要使用的双目运算符可用于这些数据类型)。
3 代码块:缩进的乐趣
代码块其实并不是一种语句,但要理解接下来两节的内容,你必须熟悉代码块。
代码块是一组语句,可在满足条件时执行(if语句),可执行多次(循环),等等。代码块是通过缩进代码(即在前面加空格)来创建的
在同一个代码块中,各行代码的缩进量必须相同。
在很多语言中,都使用一个特殊的单词或字符(如begin或{)来标识代码块的起始位置,并使用另一个特殊的单词或字符(如end或})来标识结束位置。
在Python中,使用冒号(:)指出接下来是一个代码块,并将该代码块中的每行代码都缩进相同的程度。发现缩进量与之前相同时,你就知道当前代码块到此结束了。
4 条件和条件语句
4.1 这正是布尔值的用武之地
你多次遇到了真值,现在终于需要用到它们了。真值也称布尔值,是以在真值方面做出了巨大贡献的George Boole命名的。
用作布尔表达式(如用作if语句中的条件)时,下面的值都将被解释器视为假:False None 0 "" () [] {} ,换而言之,标准值False和None、各种类型(包括浮点数、复数等)的数值0、空序列(如空字符串、空元组和空列表)以及空映射(如空字典)都被视为假,而其他各种值都被视为真,包括特殊值True
虽然可供选择的真值非常多,但标准真值为True和False。在有些语言(如C语言和2.3之前的Python版本)中,标准真值为0(表示假)和1(表示真)。实际上,True和False不过是0和1的别名,虽然看起来不同,但作用是相同的。
布尔值True和False属于类型bool,而bool与list、str和tuple一样,可用来转换其他的值
鉴于任何值都可用作布尔值,因此你几乎不需要显式地进行转换(Python会自动转换)。
4.2 有条件地执行和 if 语句
if语句,让你能够有条件地执行代码。这意味着如果条件(if和冒号之间的表达式)为前面定义的真,就执行后续代码块);如果条件为假,就不执行(你应该猜到了)
4.3 else 子句
如果你愿意,可使用else子句增加一种选择(之所以叫子句是因为else不是独立的语句,而是if语句的一部分)。
4.4 elif 子句
要检查多个条件,可使用elif。elif是else if的缩写,由一个if子句和一个else子句组合而成,也就是包含条件的else子句
4.5 代码块嵌套
你可将if语句放在其他if语句块中
4.6 更复杂的条件
4.6.1. 比较运算符
在条件表达式中,最基本的运算符可能是比较运算符,它们用于执行比较。
与赋值一样,Python也支持链式比较:可同时使用多个比较运算符,如0 < age < 100
有些比较运算符需要特别注意,下面就来详细介绍。
相等运算符要确定两个对象是否相等,可使用比较运算符,用两个等号(==)表示【一个等号是赋值运算符,用于修改值,而进行比较时你可不想这样做】
is:相同运算符这个运算符很有趣,其作用看似与==一样,但实际上并非如此
is检查两个对象是否相同(而不是相等)。变量a和b指向同一个列表,而c指向另一个列表(其中包含的值以及这些值的排列顺序都与前一个列表相同)。这两个列表虽然相等,但并非同一个对象。
总之,==用来检查两个对象是否相等,而is用来检查两个对象是否相同(是同一个对象)
in:成员资格运算符运算符in在之前介绍过,与其他比较运算符一样,它也可用于条件表达式中
字符串和序列的比较字符串是根据字符的字母排列顺序进行比较的。
4.6.2 布尔运算符
运算符and是一个布尔运算符。它接受两个真值,并在这两个值都为真时返回真,否则返回假。还有另外两个布尔运算符:or和not。通过使用这三个运算符,能以任何方式组合真值。
5、循环
5.1 while 循环
5.2 for 循环
while语句非常灵活,可用于在条件为真时反复执行代码块。这在通常情况下很好,但有时候你可能想根据需要进行定制。一种这样的需求是为序列(或其他可迭代对象)中每个元素执行代码块
基本上,可迭代对象是可使用for循环进行遍历的对象。
鉴于迭代(也就是遍历)特定范围内的数是一种常见的任务,Python提供了一个创建范围的内置函数。
5.3 迭代字典
要遍历字典的所有关键字,可像遍历序列那样使用普通的for语句
5.4 一些迭代工具
Python提供了多个可帮助迭代序列(或其他可迭代对象)的函数,其中一些位于第10章将介绍的模块itertools中,但还有一些内置函数使用起来也很方便。
5.4.1 并行迭代
有时候,你可能想同时迭代两个序列。假设有下面两个列表:
一个很有用的并行迭代工具是内置函数zip,它将两个序列“缝合”起来,并返回一个由元组组成的序列。返回值是一个适合迭代的对象,要查看其内容,可使用list将其转换为列表。缝合”后,可在循环中将元组解包。
函数zip可用于“缝合”任意数量的序列。需要指出的是,当序列的长度不同时,函数zip将在最短的序列用完后停止“缝合”
5.4.2. 迭代时获取索引
在有些情况下,你需要在迭代对象序列的同时获取当前对象的索引。例如,你可能想替换一个字符串列表中所有包含子串'xxx'的字符串,一种解决方案是使用内置函数enumerate,这个函数让你能够迭代索引值对,其中的索引是自动提供的
![](https://i-blog.csdnimg.cn/blog_migrate/ee29e609b01a218d055ba1f210782cc4.png)
5.4.3 反向迭代和排序后再迭代
来看另外两个很有用的函数:reversed和sorted。它们类似于列表方法reverse和sort(sorted接受的参数也与sort类似),但可用于任何序列或可迭代的对象,且不就地修改对象,而是返回反转和排序后的版本
请注意,sorted返回一个列表,而reversed像zip那样返回一个更神秘的可迭代对象。你无需关心这到底意味着什么,只管在for循环或join等方法中使用它,不会有任何问题。只是你不能对它执行索引或切片操作,也不能直接对它调用列表的方法。要执行这些操作,可先使用list对返回的对象进行转换。
5.5 跳出循环
通常,循环会不断地执行代码块,直到条件为假或使用完序列中的所有元素。但在有些情况下,你可能想中断循环、开始新迭代(进入“下一轮”代码块执行流程)或直接结束循环
5.5.1. break
要结束(跳出)循环,可使用break。
5.5.2 continue
语句continue没有break用得多。它结束当前迭代,并跳到下一次迭代开头。这基本上意味着跳过循环体中余下的语句,但不结束循环。这在循环体庞大而复杂,且存在多个要跳过它的原因时很有用。在这种情况下,可使用continue,
5.5.3. while True/break成例
在Python中,for和while循环非常灵活,但偶尔遇到的一些问题可能让你禁不住想:如果这些循环的功能更强些就好了。例如,假设你要在用户根据提示输入单词时执行某种操作,并在用户没有提供单词时结束循环。为此,一种办法如下:
word = 'dummy'
while word:
word = input('Please enter a word: ')
while True导致循环永不结束,但你将条件放在了循环体内的一条if语句中,而这条if语句将在条件满足时调用break。这说明并非只能像常规while循环那样在循环开头结束循环,而是可在循环体的任何地方结束循环。
5.6 循环中的 else 子句
通常,在循环中使用break是因为你“发现”了什么或“出现”了什么情况。要在循环提前结束时采取某种措施很容易,但有时候你可能想在循环正常结束时才采取某种措施。如何判断循环是提前结束还是正常结束的呢?可在循环开始前定义一个布尔变量并将其设置为False,再在跳出循环时将其设置为True。这样就可在循环后面使用一条if语句来判断循环是否是提前结束的
6 三人行
结束本章前,大致介绍一下另外三条语句:pass、del和exec。
6.1 什么都不做
有时候什么都不用做。这种情况不多,但一旦遇到,知道可使用pass语句大有裨益
为何需要一条什么都不做的语句呢?在你编写代码时,可将其用作占位符。例如,你可能编写了一条if语句并想尝试运行它,但其中缺少一个代码块如下所示:
if name == 'Ralph Auldus Melish':
print('Welcome!')
elif name == 'Enid':
# 还未完成……
elif name == 'Bill Gates':
print('Access Denied')
这些代码不能运行,因为在Python中代码块不能为空。要修复这个问题,只需在中间的代码块中添加一条pass语
6.2 使用del删除
对于你不再使用的对象,Python通常会将其删除(因为没有任何变量或数据结构成员指向它)
>>> scoundrel = {'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'}
>>> robin = scoundrel
>>> scoundrel
{'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'}
>>> robin
{'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'}
>>> scoundrel = None
>>> robin
{'age': 42, 'first name': 'Robin', 'last name': 'of Locksley'}
>>> robin = None
最初,robin和scoundrel指向同一个字典,因此将None赋给scoundrel后,依然可以通过robin来访问这个字典。但将robin也设置为None之后,这个字典就漂浮在计算机内存中,没有任何名称与之相关联,再也无法获取或使用它了。因此,智慧无穷的Python解释器直接将其删除。这被称为垃圾收集。请注意,在前面的代码中,也可将其他任何值(
另一种办法是使用del语句,这不仅会删除到对象的引用,还会删除名称本身
事实上,在Python中,根本就没有办法删除值,而且你也不需要这样做,因为对于你不再使用的值,Python解释器会立即将其删除
6.3 使用 exec 和 eval 执行字符串及计算其结果
有时候,你可能想动态地编写Python代码,并将其作为语句进行执行或作为表达式进行计算。这可能犹如黑暗魔法,一定要小心。exec和eval现在都是函数,但exec以前是一种语句,而eval与它紧密相关。这就是我在这里讨论它们的原因所在。
6.3.1 exec
函数exec将字符串作为代码执行
然而,调用函数exec时只给它提供一个参数绝非好事。在大多数情况下,还应向它传递一个命名空间——用于放置变量的地方;否则代码将污染你的命名空间,即修改你的变量。例如,假设代码使用了名称sqrt,结果将如何呢?
6.3.2 eval
eval是一个类似于exec的内置函数。exec执行一系列Python语句,而eval计算用字符串表示的Python表达式的值,并返回结果(exec什么都不返回,因为它本身是条语句)。
7小结
打印语句:你可使用print语句来打印多个用逗号分隔的值。如果print语句以逗号结尾,后续print语句将在当前行接着打印。
导入语句:有时候,你不喜欢要导入的函数的名称——可能是因为你已将这个名称用作他用。在这种情况下,可使用import ... as ...语句在本地重命名函数。
赋值语句:通过使用奇妙的序列解包和链式赋值,可同时给多个变量赋值;而通过使用增强赋值,可就地修改变量
代码块:代码块用于通过缩进将语句编组。代码块可用于条件语句和循环中,还可用于函数和类定义中(这将在本书后面介绍)。
条件语句:条件语句根据条件(布尔表达式)决定是否执行后续代码块。通过使用if/elif/else,可将多个条件语句组合起来。条件语句的一个变种是条件表达式,如a if b else c
循环:你可针对序列中的每个元素(如特定范围内的每个数)执行代码块,也可在条件为真时反复执行代码块。要跳过代码块中余下的代码,直接进入下一次迭代,可使用continue语句;要跳出循环,可使用break语句。另外,你还可在循环末尾添加一个else子句,它将在没有执行循环中的任何break语句时执行
pass、del、exec和eval:pass语句什么都不做,但适合用作占位符。del语句用于删除变量或数据结构的成员,但不能用于删除值。函数exec用于将字符串作为Python程序执行。函数eval计算用字符串表示的表达式并返回结果。