Python基础-一般控制结构

本文为《爬着学Python》系列第七篇文章。


我们拖了好久,终于要开始真正进行Python语法的讲解了。是的,变量与对象只是Python的语义特征,编程语言的语法特征体现在控制结构。

也就是我们一般说的if,while。

我们今天要讲的主要就是这两种控制结构,即判断和循环结构。而且,我们涉及的是非常简单而朴素的控制结构。关于迭代器、生成器、高级函数等知识会在Python进阶部分进行讨论。我们先打好基础,后面学起来会比较轻松。

判断

判断结构一般也叫条件判断结构,简单理解起来,如果满足什么条件,那么进行什么样的操作。实现方式一般是if语句

我们直接在if后面接上判断条件即可完成判断,换行后空四个空格进行根据判断结果的执行部分。

if 条件:
    执行语句
条件判断结构以外的执行语句

注意到我们不需要任何形式的括号来包住执行部分,Python通过缩进判断语句的结构。当你的缩进与if语句对齐时,自动退出条件判断结构。在命令行中,我们通过空行来实现退出:

>>> a = 3
>>> if a > 2:
...     print('a is bigger than 2')
...
a is bigger than 2

简单的判断语句结构就是这样。当if后面的条件满足时,就会执行判断结构中的执行语句,否则直接跳过执行部分推出判断结构。

布尔值

为了进一步了解条件判断结构,我们需要了解一下布尔值这种数据类型。

>>> type(True)
<class 'bool'>

布尔值分为两种,TrueFalse,即我们一般所说的“真”和“假”。在Python中布尔值一般有两种出现方式,一种是直接赋值给变量,一种是通过判断来得到。

>>> a = True
>>> if a:
...     print('a')
...
a
>>> if a is True:
...     print('a is True')
...
a is True

其中,a = True是直接把布尔值True赋给变量a,所以我们把a当作判断条件的时候,程序会完成执行部分。而a is True则是在进行判断,这个判断的结果为True,所以程序一样会完成执行部分。

而我们所谓的“进行判断”,其实可以看作条件判断结构中会自动对判断条件调用bool()函数。

>>> bool(a > 3)
False

事实上,之前提到的条件判断结构中if 条件:根据条件返回的的布尔值来进行判断完成功能的。条件返回值为True则执行,否则不执行。这也是为什么if a:可以当作判断条件。

布尔值其他细节

我们知道了if 条件:在进行判断时,实际上是在判断条件表达式返回的布尔值。因此返回布尔值的任何对象都可以作为判断条件。

常见的是值的大小比较,即><>=<=。很好理解,它们分别对应“大于”、“小于”、“大于等于”、“小于等于”。

我们要特别把等于单独说是因为,我们不能直接用等号来判断是否等于,例如if a = 3:,我们很清楚a = 3是个赋值语句,这样会造成歧义。因此,在判断相等时,我们连用两个等号if a == 3:,不等于的形式为if a != 3:

之后我们需要知道的,就是布尔值的简单逻辑运算,包括“与”、“或”、“非”,Python中分别表示为 andornot

  • 条件A 与 条件B在两个条件都为真时整个表达式的布尔值为真,否则为假。
  • 条件A 或 条件B在两个条件都为假时整个表达式的布尔值为假,否则为真。
  • 非 条件直接反转条件的布尔值。

我们可以看出andor是二元操作符,not是一元操作符。

布尔值的逻辑结构可以组合使用,其中andor结合优先度高于not,但为了代码可读性,还是建议在组合逻辑结构中使用括号方便理解。

>>> a = 3
>>> if not (a > 2 and a < 4):
...     print(a)
...
>>>

最后要补充一点的就是,除了布尔值以外,其实还有一些情况也能作为判断条件。

>>> if a:
...     print('a')
...

但我们直接把变量当作判断条件时,它也可以不必是布尔值,对象直接作为判断条件会返回一个布尔值。对于整型和浮点数来说,0为假;对于简单数据结构,包括字符串,它的内容为空时是假;最后None是假。

None就好像布尔值变量一样是一种特殊的数据类型。它的类型叫作无类型

>>> type(None)
<class 'NoneType'>

再举几个例子验证一下:

>>> bool(0.0)
False
>>> bool([])
False
>>> bool(None)
False
>>> bool([None])
True
>>> bool('None')
True

最后还要提醒一点,不要轻易用浮点数当作判断条件。因为Python中是把一个极小的浮点数作为0来使用的。

>>> bool(1e-323)
True
>>> bool(1e-324)
False

判断结构中的else

我们刚才说的判断结构的逻辑是,如果满足条件就做一些对应的事情,否则不做。其实,判断结构还可以完成:如果满足条件就做一些对应的事情,否则做另一些事情。使用else就能完成这样的功能:

>>> a = 3
>>> if a > 4:
...     print('a is bigger than 4')
... else:
...     print('a is not bigger than 4')
...
a is not bigger than 4

这种结构比较简单,易于理解。

事实上,else 还可以再次进行判断,但我们要用elif来完成更具体的条件判断结构:

>>> a = 4
>>> if a > 4:
...     print('a is bigger than 4')
... elif a < 4:
...     print('a is smaller than 4')
... else:
...     print('a is equal to 4')
...
a is equal to 4

如果使用这种结构根据不同情况分别处理时,不管有没有穷尽所有可能,都建议最后留出一个else:来处理一些其他情况防止遗漏。

关于条件判断结构,最后要说的是,Python并不具有switch结构,可以用字典检索通过表驱动的方式来完成这样的功能。

def function_1(...):
    ...

functions = {'a': function_1,
             'b': function_2,
             'c': self.method_1, ...}

func = functions[value]
func()

详见Design and History FAQ — Python 2.7.13 documentation

循环

讲过判断结构以后再来讲循环就简单了。我们知道条件判断结构是用来让程序根据某种条件做或者不做某种事情。当我们需要程序重复做某件事情的时候,我们就需要循环结构了。

Python循环结构主要有两种实现语法,一种是按条件循环,一种是按次数循环,对应的方法分别是whilefor

while简单使用的具体结构如下:

while 条件:
    执行语句
循环结构以外的语句

不难看出,while的用法和if大同小异。区别在于,if只判断一次条件,程序顺序执行;while重复判断,只要条件满足,程序重复执行,直到条件第一次不满足为止。

>>> a = 3
>>> while a > 0 :
...     print(a)
...     a -= 1
...
3
2
1

上面这个控制结构实现的功能很简单,依次输出小于等于a的所有正整数。我们实现的方法是输出a之后把a减去1,直到a不大于0了停止。

while循环结构中,我们的条件部分工作原理和判断结构中相似。但在循环结构中,有一个新的问题,一般来说,循环结构需要一个“出口”来停止循环。这个出口有两种实现方式,一种是通过破坏判断条件来退出,一种是在循环结构内部设计判断结构来退出。我们先讲前者,后者在介绍完for循环结构以后再讨论。

正如刚才的示例循环结构一样,当循环条件可变时,程序就有可能退出。而我们设计循环结构时,会有意地设置循环条件,让程序在适当的时候退出循环结构。我们可以在执行语句的基础上增加一个变量作为循环次数的“计数器”:

>>> i = 0
>>> while i < 3 :
...     print('hello')
...     i += 1
...
hello
hello
hello

在这个程序中,变量i没有实际意义,它是用来保存循环次数的变量。可以看得出来,我们在使用i之前要对其赋值进行初始化,再进行使用,这很不方便。事实上,while语句更多的是用来进行循环次数不可知或者量极大时才会使用的,有事我们会看到while True:这样的语句,这是无限循环,会永远进行下去。对于循环次数比较确定的场景,for循环结构更加得心应手。

for循环的一般结构如下:

for 变量 in 范围:
    执行语句
循环结构以外的语句

其中变量是用来标记范围中的元素,方便在执行语句中对其进行操作或者引用;范围是个可迭代对象(iterable),一般来说是简单数据结构如列表字典等,也可以是迭代器,最简单的是range类型的对象。我们刚才说到ifwhile在判断条件时会自动调用bool()函数,其实for语句一直在调用next()函数,相关内容以后深入,目前了解即可。

range是外形最为原始的Python内置类。定义方式就像普通类,range接受3个参数range(a, b, c),你可以把它看作会生成一个以a为首项,c为公差,元素小于b的列表。当只给两个参数时,默认c=1,当只给一个参数时,默认a=0, c=1

我们之前while中的例子可以改写为:

>>> for i in range(3):
...     print(i + 1)
...
1
2
3

关于for方法的一些技巧性的操作,会在以后的简单数据结构和函数式编程相关内容中进一步介绍。

break和continue

我们之前提到,退出循环有两种方式,一种是通过破坏循环条件退出,另一种,就是在循环结构内部退出。

首先,return会跳出当前函数运行环境,因此在循环体内可以作为退出的方式。我们可以在函数体内部增加一个判断结构,在某个变量满足某个条件时,函数取得返回值,程序退出循环结构所在的函数。

不过return不是我们要讲的重点,有关内容会在程序结构设计等内容中讨论。我们要说的是breakcontinue,我们作为比较将两者一起讲。

>>> for i in range(3):
...     print('running')
...     if i > 0:
...         break
...     print(i)
...
running
0
running

break会直接退出循环结构。

>>> for i in range(3):
...     print('running')
...     if i > 0:
...         continue
...     print(i)
...
running
0
running
running

continue跳过循环结构中本次执行过程中continue后面的执行语句,但是不会破环循环使其结束,循环会从循环变量的下一个值继续运行,继续判断,继续执行,直到循环结构有其他出口退出循环。

循环结构中的else

我们刚才判断结构最后说了一个else的功能,即规定在判断条件不满足时才执行的语句。其实循环结构中也可以使用else关键字,但是应用场景不是很多。

>>> for i in range(3):
...     print('running')
...     if i > 0:
...         continue
...     print(i)
... else: 
...     print('ending')
...
running
0
running
running
ending

可以看到上面的这段脚本输出结果是不一样的。在这里,只是为了展示一下while语句中else的格式,要注意不能把elseif对齐,否则就成了判断语句的一部分了。

else在循环结构中的功能为,如果循环条件没有被破环即循环次数用完后正常退出循环结构,则执行else部分的语句,否则跳过。所以else往往是和continuebreak搭配使用,这也是为什么要先讲循环的退出再讨论循环中else的运用。循环中的else在各种项目中见得不多,主要是因为会影响代码的可读性。只要能理解别人代码中出现的这种结构就可以了,对控制结构操作技巧要求较高的可以尝试使用。

熟练运用控制结构的功能是必备的能力,这需要积极练习加深理解。实际运用中,尤其是面向过程时,我们会将判断和循环结构交相嵌套,完成相应的复杂功能。这些都会在以后的深入学习中逐渐接触。


至此,我计划中的Python基础部分就算告一段落了。我们第一次接触了Python对象的概念,我们见识了Python简单数据类型的使用方式,我们初步了解了Python中控制结构的形式。这就算有一些Python基础了。
接下来我们会开始尝试Python的实际使用,我们需要了解Python的内置数据结构的基本用法,我们需要学会定义函数集成一些简单的功能,我们需要了解Python第三方库的使用方法和管理工具,之后,我们就可以开始尝试编写第一个爬虫了。


链接

  1. Design and History FAQ — Python 2.7.13 documentation
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容

  • 前言 ||| 第二章 使用ArcPy编写脚本 Python支持大部分在其他语言中出现的编程结构。在本章内容中,我们...
    muyan阅读 90,039评论 10 55
  • 一、python 变量和数据类型 1.整数 Python可以处理任意大小的整数,当然包括负整数,在Python程序...
    绩重KF阅读 1,700评论 0 1
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,419评论 0 17
  • 最近在慕课网学习廖雪峰老师的Python进阶课程,做笔记总结一下重点。 基本变量及其类型 变量 在Python中,...
    victorsungo阅读 1,687评论 0 5
  • 今天2017年9月16日中午12点10分,一如既往的无聊才会想起梦想的我来看看前几天的梦想有没有撞上上帝瞎了眼。果...
    胜天半子x阅读 165评论 0 0