第二讲 Python基础 DONE
Table of Contents
1 命令行
我们已经接触了几个基本命令,
- ls
- 意为 “list structure”,列出当前文件夹下的所有文件。
- cd
- 意为 “change directory”,改变当前路径的位置,跳到另一个文件夹里。
- sudo
- 意为 “super user do”,用最高权限来执行指令。
- apt
- 缩写是“Advanced Package Tool”,是软件包管理器,有些默认的环境里面没有 python3,我们是通过它来安装上 python3。
- vi
- 是文本编辑器,这个编辑器不是当前流行的风格,但是非常强大,如果同学们有机会去深入学习这个编辑器,会发现它是完全是另外一个非常强大的世界。
- nano
- 也是文本编辑器,相比 vi 简单易上手。
- emacs
是我使用的文本编辑器,基于 Lisp 语言定制性极强。
“现代”风格的文本编辑器至少有一个窗口,有菜单,有光标,但这是1990年代发展出来的。对 vi 和 nano 这样的风格,操作都通过 Ctrl-W,Ctrl-X 等快捷键完成,同学可能不太适应。nano 编辑器确实较简陋,只进行基本的操作,不是主力用编辑器。这些编辑器是应急使用,做一些快速简单的改动。每个人都会发展出自己的编辑器偏好,发展出自己最喜欢的工作方式,在学习的过程中要慢慢体会。vi 和 emacs 的学习曲线都比较陡峭。最开始的三天会感觉自己在和自己打架,但一个星期之后,就会发现与计算机的沟通有一个巨大的飞跃。
POSIX 环境的设计理念是每一个命令都要完成且仅完成一件小事,这叫做“Do one thing, do it right”。这可以促进分工协作:用户可以把各类小巧的工具挑选出来,组合起来,应用各种各样的场景,有无限可能。连工具的设计者都没有办法预测出来用户究竟是怎么用他的命令的。
无穷无尽的组合可能,会让大家在入门时迷茫。世界太大了,我们要挑选一条路会很难受,特别是选择较困患者。一旦能够入门,它将是威力巨大的一个技能。我们不要求每位同学都能够入门,大家掌握能够完成作业所需要的最小限度。感兴趣的同学可以选择一个命令环境的自学教程。注意国内教程和博客的水平水平参差不齐,经常在博客中会有很多错误的信息,大家在查资料时不要误入歧途。
初学命令行时,会有非常多的不适应。为什么要学习 POSIX 这个“反直觉”的系统呢?在大规模数据处理和科学计算中,我们站在世界的前沿。并没有其他的开发者,给我们开发出现成的工具来完成科学任务。但是这个环境里面的很多小工具——连开发者也不知道能够被用在科学计算上——反而会更加有效地完成任务。如果一个学科发展出了成熟的工具,让我们可以点几下鼠标就可以制出一个完美的图,那么这个学科就已经发展成为工业级了。如果在实验室中有这样的程序,可能是学长给大家准备了这样的比较友好的界面,但是这些界面往往年久失修会有各种bug。掌握命令行的技能非常有用,它只是入门时有些痛苦,但适应之后,你会发现它成为思维的一部分。我非常希望能看到一部分同学能够理解这一点,今后掌握这些小工具创造出来前所未有的组合方式和操作方式。
Git 给我们一个“时光机”,能够高效地记录自己过去的工作进展。同时在空间上,Git 辅助团队协作,可让大家互换差分,高效协同。这种合作模式促成和造就了全世界的大规模的项目的崛起。
1.1 图形界面
Git的客户端中,也有许多图形界面的,但是都不大好用,常有玄学错误。而且很难修改和定制。目前命令行的Git是“最佳工具”。
1.2 加密
很多同学是第一次手动操作加密通道,我们看到在网络空间人与人是如何互相验证和建立信任的。如果这些加密可信,我们就可以与队友和远程的服务器不断地交换差分。这部讲义就是这样协同创作的。
1.3 学习要领
《实验物理的大数据方法》涉及的内容很杂,与物理学其它学科很不一样。碎片化的知识和技能不成体系,需要点滴的积累。可以用造房子来比喻,房子的最终成品有居住的功能,但是在准备材料时,要铁、砖、木头,这些东西之间好像没有什么联系。初学大数据方法时就大概处于这样一个阶段,头绪很多,但是所有材料都是马上都会用到的,并不是孤立的技能。
当今特别强调可复现研究和开放科学,当发布一个论文时,数据和处理方法,图和表格的程序都应与论文一起发布在共享协作平台上,例如 GitHub。
2 Python
我们从 Python 程序的基本构建、变量和数据类型学起。Python 是一门解释型语言,相对于编译型语言如 C/C++ 它更容易调试。在解释型语言中,可以直接看变量结构是什么,而编译型的需要特别的调试器来进行。Python 的语法风格简单,没学过 Python 的人看了一遍 Python 程序,也能够大概地读懂。最近突然出现了这么多程序员,Python 的简单起了很大作用。Python 还可以直接调用很多其他的库。Fortran 是从 1960 年代开始的科学计算的基本语言。经过多年的积累,有大量优秀的一个科学数据处理、微分方程等工具库。Python,还可以调用从前的工具,大大地丰富了 Python 的科学计算能力。同时它也可以调用C/C++,R语言等。 Python 的特性不仅可以使它自己的功能增强,还可以使团队合作更加顺畅。
Python 是一个通用的语言,不仅用于科学研究,在生活中使用得更多。Python 可用来生成和管理操作系统,如 Gentoo Portage 是我目前参与的项目。Python 还可以构建极简的网站服务器,如我们的大作业平台的评分系统由 Python 写成。Python 易于上手,易于开发,在实际中应用广泛。希望大家能够能够喜欢上python。
2.1 参考资料
课上没有办法覆盖 Python 的方方面面,许多细节和新功能需要自学。Python 有很多学习资料,对自学非常友好。Python for Everybody 是一个简明通俗的入门教材,甚至适合没有高等教育基础的大众自学,书中非常友好地解释每一个程序元素背后的理念和目标。初学 Python 时,这本书读起来会很开心。编程基础比较强的同学,可以使用 https://learnxinyminutes.com/ 在一小时之内快速入门 Python。它把 Python 所有的例子都总结到了一个网页。同理,如果你在这门课上掌握了 Python,在研究中需要快速入门其它语言,也适合使用这个网站,通过例子把 Python 的技能迁移到其它语言。 虽然教学的内容是借助 Python 跟大家表达的,在实际中不要把思想拘于 Python,世界很广阔。
2.2 运行环境
注意 Python 存在两个版本主要版本,Python 2 和 Python 3。当 Python 发展到 Python 2时,已经是流行语言。开发者开始反思,总结了犯过的错误,希望在计划一个大版本进行改正。但这会导致现有的程序无法使用。怎么办呢?加了一个版本号,可执行程序的名字也不一样,叫 python3
。这样,新版程序用 python3
执行,旧版程序用 python2
执行。
进入 Python 3 的环境,需要用 python3
命令。Python 有一个增强的互动环境,IPython。“I”的意思是 interactive。这个环境好在有智能补全,在交互性操作时比较友好。如果你的环境里没有 ipython3,可以使用 apt install ipython3
来安装。Python 的另一个运行方式是 Jupyter ,它由 IPython 发展而来,好处是可以在网页上来进行 Python 操作,交互性更强,可以规避掉命令行,适用于探索。坏处是网页操作没有优秀的编辑器可用,写大段程序不大顺手,并且网页环境的批量处理能力很弱。
Jupyter 使得 Python 的应用更广,有了更多的用户在网页上编程。这是个双刃剑,一方面基础很差的人,摸了几下 Jupyter 试了几种肤浅的操作,就以为自己学会了编程,到处招摇过市;另一方面,一个工具,可以受到全社会的关注,是非常荣耀的事。我推荐大家了解 Jupyter,把它与命令行组合使用,发挥最大的威力。但是它不能替代命令行工具。
2.3 基本算术运算
可以做基本运算,还有一些其他的运算比如乘法。2的7次方是这样写,两个乘号。
2**7
128
3/2是是严格的除法,
3/2
1.5
如果要整除的话写 3//2。
3//2
1
3%2 是取它的余数。
3%2
1
也可以使用高级功能,比如阶乘,阶乘需要使用使用 math 的库,要 import math
。3的阶乘是6,66的阶乘多大?
import math math.factorial(66)
544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000
这是 Python 的重要特点,整数是高精度的。在计算机的硬件里,每个数都要内存空间存储,我们如果学习C语言,需要知道有些整数用16比特,有些占用32比特,有些占用8比特,有的占用64比特。整数的范围是因定的。Python 又进行了一层抽象,使用软件实现了高精度的整数,在计算机可承受的范围内无上界。试试2的10000次方,
2**10000
19950631168807583848837421626835850838234968318861924548520089498529438830221946631919961684036194597899331129423209124271556491349413781117593785932096323957855730046793794526765246551266059895520550086918193311542508608460618104685509074866089624888090489894838009253941633257850621568309473902556912388065225096643874441046759871626985453222868538161694315775629640762836880760732228535091641476183956381458969463899410840960536267821064621427333394036525565649530603142680234969400335934316651459297773279665775606172582031407994198179607378245683762280037302885487251900834464581454650557929601414833921615734588139257095379769119277800826957735674444123062018757836325502728323789270710373802866393031428133241401624195671690574061419654342324638801248856147305207431992259611796250130992860241708340807605932320161268492288496255841312844061536738951487114256315111089745514203313820202931640957596464756010405845841566072044962867016515061920631004186422275908670900574606417856951911456055068251250406007519842261898059237118054444788072906395242548339221982707404473162376760846613033778706039803413197133493654622700563169937455508241780972810983291314403571877524768509857276937926433221599399876886660808368837838027643282775172273657572744784112294389733810861607423253291974813120197604178281965697475898164531258434135959862784130128185406283476649088690521047580882615823961985770122407044330583075869039319604603404973156583208672105913300903752823415539745394397715257455290510212310947321610753474825740775273986348298498340756937955646638621874569499279016572103701364433135817214311791398222983845847334440270964182851005072927748364550578634501100852987812389473928699540834346158807043959118985815145779177143619698728131459483783202081474982171858011389071228250905826817436220577475921417653715687725614904582904992461028630081535583308130101987675856234343538955409175623400844887526162643568648833519463720377293240094456246923254350400678027273837755376406726898636241037491410966718557050759098100246789880178271925953381282421954028302759408448955014676668389697996886241636313376393903373455801407636741877711055384225739499110186468219696581651485130494222369947714763069155468217682876200362777257723781365331611196811280792669481887201298643660768551639860534602297871557517947385246369446923087894265948217008051120322365496288169035739121368338393591756418733850510970271613915439590991598154654417336311656936031122249937969999226781732358023111862644575299135758175008199839236284615249881088960232244362173771618086357015468484058622329792853875623486556440536962622018963571028812361567512543338303270029097668650568557157505516727518899194129711337690149916181315171544007728650573189557450920330185304847113818315407324053319038462084036421763703911550639789000742853672196280903477974533320468368795868580237952218629120080742819551317948157624448298518461509704888027274721574688131594750409732115080498190455803416826949787141316063210686391511681774304792596709376
这是 Python 的一大特色,它样做需要经过许多诸如内存判断,用多少内存,数量还会变化,多重判断会降低效率。但是现在计算机硬件水平,用效率损失来换取方便的接口是值得的。这也是本课程的基本价值观:如果能够节省人类的时间,不惜浪费计算机的时间。这与计算机专业研究有区别:计算机研究的目标,是让它更快,算法更巧妙,效率更高。
整除有一些基本的约定,看几个例子
-5 // -3
1
-5 // 3
-2
往下面降。要注意,有些语言不是这样的约定,而是按照绝对值最小的方向去去降,那么-5整除3会给出-1。
(-5 // 3) * 3 + (-5 % 3) == -5
True
除号和取余号也可以用在浮点数上。
2.4 布尔运算
布尔运算得到“真”“True”或者“假”“False”,是数理逻辑的范畴。否命题
not True
False
not False
True
and
和 or
和数理逻辑的“和”跟“或”的定义是一样的。它的内部表示和其他语言很类似, True
和 False
不是全新的数据类型,它内部以数字形式存储。
True + True
2
严格的数理逻辑中,只是01运算,组成的加法群中, True + True
应该还是 True
。但是Python 中结果变成了 2。
2 and True
True
此时 2 与 1 一样,都被当作 True
处理,即非零整数被在逻辑运算中是一个等价类。
Python 的设计符合直觉和数理逻辑的定义。如果在布尔运算中用乘法也是自恰的,因为 True
是非零, False
是 0。这可以帮助我们理解 True
和 False
的实现。
实际应用中 True
和 False
源于条件判断,如等号。“=”已经被赋值占用了,条件判断用“==”
1==1
True
1==2
False
“不等于”在python里边是“!=”。
2.5 数据类型
Python 有三个基本数据类型:
- 整型
- 我们刚看到的精度无限的整数;
- 浮点型
- 精度是有限的,常见的是64位高精度;
- 字符串
- 单个字符也是字符串,这与 C 语言不同。字符串拥有无限长度,在软件上把它进行了便利的实现和抽象。
type(1)
<class 'int'>
type(1.5)
<class 'float'>
"今天" + "下雨了"
今天下雨了
字符串用单引号和双引号都可以,一个好处是字符串里要输入一个单引号,可用双引号来引用。
"'"
'
'"'
"
这是双引号。 Python 3 所有的国际语言的符号都可内嵌到语言里,字符串可以直接使用汉字。相对于更基础的语言如C/C++,可以给我们非常大的便利。大家已经约定良好的处理字符串的方法都已经被 Python 作为默认功能。要入门程序语言,我们要打印“Hello World!” 向前人致敬。
print("Hello, world!")
Hello, world!
Print 是 Python 的一个函数,里面可加一个字符串。
2.6 变量
Python 的变量与数学的含义类似,用以指代一个任何对象,例如字符串,
message = "This is an new era. 新时代" print(message)
This is an new era. 新时代
那么随后就可以用变量代替字符串。Python 的一大的特点是变量没有类型。我们可以看到,
message = 3840752916 print(message)
3840752916
message
这个变量既可以是字符串,也可以是整数。 Python 是无类型语言,这是很强的假设。如果语言的变量没有类型,那么它在运行中每次调用 message
时,都要检查它到底是什么类型。可以想象这样做需要额外的步骤调取内部的函数和库,Python 损失了很多效率。但是,我们喜欢!因为人类的脑子里也不区分整型、浮点型和字符串。Python 用它上层的软件库,给人带来了很多的便利,符合直觉是 Python 语言的一大特点。在做科学计算时,这个问题没那么简单了。学习 Numpy 时我们将看到,无类型变量的效率太低,我们只能再放弃一点便利,为了性能规定变量类型。
变量本身也可以赋值给另一个变量,
m = message print(m)
3840752916
input()
与 print()
对应,可以用来输入变量。例如:
# q = input("Enter anything: ") # 输入 47042 q = "47042" # 结果 type(q)
<class 'str'>
注意得到的变量类型是字符串,如果需要数字,需要转换成整型。
type(int(q))
<class 'int'>
2.7 标准输入
print
可以把信息打到标准输出,也就是屏幕上。那么如何从外界输入给程序信息呢?接下来学习输出变量的命令 input
。
5
x = input()
接到提示把数字 "5" 输入进来,赋值给了 x
。此时 x
是 "5" 字符串。我想输入数字,这就需要转换它。
标准输入使程序可与外界交互,输入信息被赋给了变量。输入可以由人给出,也可以由其它程序给出。前一程序的输出成为后一个程序的输入,可以让信息在程序之内流动。
2.8 行编辑命令
不论是在 Python 的交互环境,还是在 shell 中,都可以使用“行编辑”命令来辅助输入。例如,“Ctrl-r” 用来搜索之前的指令,“Ctrl-s” 向后搜索,适用在 Python 环境里输入了较多命令时。行编辑功能是命令行的通用功能,由基本的 readline
库实现,在 shell 环境里,也可以用 Ctrl-r 和 Ctrl-s 来进行搜索,可以避免重复输入 ls
一类命令。
2.9 汇报问题
ipnut()
我们在操作计算机时,会经常看到英文的出错信息。遇到问题不要慌,仔细看一下 Trackback
上的提示。
Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'ipnut' is not defined
我们处于交互模式,所以是 File "<stdin>"
,表示是从标准输入(standard input,缩写为 stdin)执行的程序。接下来显示 NameError
,告诉我们单词 "input" 拼错了。 初学者很容易见到长串的出错信息就感觉就立刻焦虑,想要赶紧切换方法。盲目尝试了其他方法,又发现其它的错误信息。
遇到出错信息怎么办?求助时,若只讲“报错啦”,他人会追问具体报出什么出错信息。解决问题的要点都在错误信息本身。因此要非常重视这些信息,初次见到它未必容易理解,比如涉及了像 Traceback
和 stdin
这样的生词和术语。克服了它们,我们积累了经验就能够迅速定位到问题的关键。
2.10 分号
Python 的 “;” 相当于一个快捷的换行,用于把多个语句写在一行里。例如
x = 23; y = x; print(y-1)
22
3 字符操作
3.1 字符串基本操作
字符串长度不确定,而且其中不全是传统的英文字母,处理起来复杂。相对于硬件的底层调用,字符串是一项高级工艺。Python 有强大的字符串工具库。 我们已经看到“1”和“2”,如果不转成整型,就会变成字符串加法,成为“12”。同理 “A”+“B”等于“AB”,就是把它们连起来。字符串乘以数字定义为重复。符合直觉,“A”+“A”加8次就是8个A,乘法是加法快捷方式。
print("A" * 8)
AAAAAAAA
求字符串的长度使用 len()
函数,取“length”之意。例如
print(len("123456")) print(len("654321"))
6 6
它们的长度都是6。
3.2 字符串替换
我想把一个句子分成变的部分与不变的部分,例如“什么乘以什么等于什么”。
"{}乘以{}等于{}".format(3, 5, 3*5)
'3乘以5等于15'
句式不变,变的部分用 {}
表示, .format()
中的参数与前面的 {}
一一对应,分别是 3, 5, 15。当调用的是变量时,可以写在 .format()
的参数中,更方便的方法是“f-string”,例如,
a = 3 b = 5 f"{a}乘以{b}等于{a*b}"
'3乘以5等于15'
3.3 字符串的子串
用 []
把字符串中的字符或者子串取出。例如
s = "我正在上课" s[0], s[2:4], s[-1]
('我', '在上', '课')
“0”代表最先的字符,“2:4” 是从2到4的左闭右开区间,即 2,3,“-1”代表最后一个字符元素,“-2”是倒数第二个。在整数的论域中,左闭右开区间的特殊好处是可以直观地把相邻的区间写下来,“0:2”,“2:4”,“4:5”都是首尾相邻且不重叠,边界上的2属于“2:4”,4属于“4:5”。这在实现批量处理逻辑中非常方便。参见 Dijkstra 的经典短文 EWD 831,“Why numbering should start at zero”。
3.4 标准库中的字符串操作
Python 的官方文档详尽介绍了标准库中字符串的进阶操作,这里我们选取几个常用的介绍。
count()
函数可以统计字符出现的次数,例如
s = "今天的气温是 30 摄氏度,明天是 29 摄氏度" s.count("天")
2
startwith()
用来判断字符串是否由某个子串开头,
s.startswith("今天")
True
split()
将字符串按照给定的分隔符分成列表,在处于有格式约定的文字时经常用到。
s.split(",")
['今天的气温是 30 摄氏度', '明天是 29 摄氏度']
replace()
用于一一替换字符
seed = bin(2324) print(seed) print(seed.replace('0',"奥").replace('1',"利"))
0b100100010100 奥b利奥奥利奥奥奥利奥利奥奥
bin
将整数转换成字符串的"0"、"1"二进制表示,用 replace()
把它映射到自定义的奥利奥配置。
在使用这些高级操作时,注意体会 Python 标准库相比其它语言的便利性。很多实现起来复杂的操作在 Python 中默认都是一个函数完成。非常值得先浏览一遍标准库提供的函数,有了第一印象方便灵活运用。
3.5 None 值
Python 中一个特别的值,即不是整数也不是浮点数,属于一种独有的类型,叫做“None”,可以代表很多含义:“空”或者“没有”,或者“无法表达”,或者“出错了”、“非法”。它本身也是一个值,可以 print
,可以赋值,例如:
print(None) x = None 2 == None, x == None
None (False, True)
转换为布尔类型时,None 的赋值为“假”。
bool(None)
False
4 基本程序结构
计算机程序可以分成三种结构。
一是顺序结构,即至今为止我们举的例子,语句从前到后依次执行。二是选择结构,亦称分支,根据条件是否成立,选择执行哪个语句。三是循环结构,即重复执行的结构。
4.1 选择结构
选择结构的基本语法是 “if…else”,例如
x = 23 if x % 2: print(f"{x}是奇数") else: print(f"{x}是偶数")
23是奇数
我们就判断了一个变量的奇偶性,如果 x % 2 = 1 ,判断为“真”,执行第一个语句,反之则执行第二个。上面的例子展现 Python 通过缩进来表达程序中的层次,“奇数”语句和“偶数”语句都是通过空格缩进表达它隶属于 if
和 else
的两个部分。强大的程序编辑器非常重要,可以自动帮我们给出统一的缩进量。合适的程序编辑器,甚至能够自动识别“else:”,与上面 “if” 的语句体区分开,向前缩进。结合语法高亮颜色标识与提示,是书写程序是最重要的助手。
GNU nano 在这方面就不够强,我们需要手动给出空格的数量。但这样多一个少一个空格上下不统一时容易出错。
C语言使用 “{}” 作为语法的界限,Python 很不同,默认规定都写成良好缩进的。C 语言中缩进只是为了美观,Python 的缩进则是语法的一部分。Python 的设计理念是,既然我们都鼓励美观的缩进,那不如把它强制实行。
选择有三个时,“else if” 可以缩写为 “elif”。例如:
x = 23 if x % 3 == 0: print("A") elif x % 3 == 1: # 也可以写作 else if x % 3 ==1: print("G") else: print("S")
S
在 if
嵌套时, else
与 if
的对应关系取决于缩进的量,例如
x = 23 if x % 2 == 0: if x % 4 == 0: print("X") else: # 与第二个 if 对应 print("M") else: # 与第一个 if 对应 print("A")
A
4.2 循环结构
Python的循环结构有两种, for
语句和 while
语句。除了与其他语言相似的标准循环功能之外,还有 Python 特有的用法。举一个简单的例子,
a = 0 while a < 5: print(a) a = a + 1
0 1 2 3 4
这4条语句,先把 0 赋予 a
。只要 a
小于 5 就持续循环,每次循环输出 a
并给 a
加 1。第一次循环,输出 “0” , a
变成了 1,下一次循环,输出 “1”, a
变成了 2,……
同样的逻辑可以用 for
循环更简洁地实现:
for a in range(5): print(a)
0 1 2 3 4
但原理有所不同。 range()
返回一个“迭代器”(iterator),在每次 for
循环时,都从迭代器中取出一个值。 range()
为 for
准备了从 0 到 4 一共 5 个数字,注意这是从 0 到 5 的左闭右开区间。
借助迭代器,程序变量更简洁。为了简化程序,增强语义的表现力,Python 有许多地方都语法上的快捷书写方法。
迭代器是一般概念,Python 中的多数多个元素组成的数据结构都可以看作迭代器。字符串就是一个例子,
s = "我爱吃瓜,瓜好甜。" for x in s: print(x)
我 爱 吃 瓜 , 瓜 好 甜 。
“s” 由 9 个字符组成。for 循环就循环 9 次,遍历所有元素。这是迭代器设计的精妙之处,如果没有迭代器,我们只能这样写:
for i in range(len(s)): print(s[i])
我 爱 吃 瓜 , 瓜 好 甜 。
显得比较笨拙。人类在思考时完全不管下标,自然是“把字符一个一个打出来”,而不是“先输出第1个字,再输出第2个字,……”。
有时我们既想用迭代器,又想得到索引,使用 enumerate
for i, x in enumerate(s): print(f"第{i}个字是'{x}'")
第0个字是'我' 第1个字是'爱' 第2个字是'吃' 第3个字是'瓜' 第4个字是',' 第5个字是'瓜' 第6个字是'好' 第7个字是'甜' 第8个字是'。'
4.2.1 break
在循环里执行 continue
,可以跳过本次循环进入下一步。执行 break
则终止循环,直接跳出循环体。例如:
for i in range(10): if i % 2: continue print(i)
0 2 4 6 8
会跳过所有奇数。换成 break
则会提前退出,
for i in range(10): if i % 2: break print(i)
0
4.2.2 死循环
一个循环的终于条件如果永远无法满足,则会成为死循环。例如
while True: pass
pass
是循环体的占位符,代表什么也不做。Python 使用缩进表循环语句体的语义,当语句体为空时要用占位符来表示。