五、循环和逻辑
有时候打击犯罪会让你觉得自己在兜圈子。日复一日,你似乎不得不处理相同的斗争:这里的银行抢劫犯,那里的一只困在树上的猫,一个邪恶的天才试图接管宇宙。这就好像你陷入了某种…循环。
虽然被困在众所周知的土拨鼠日——这一天一遍又一遍地重复,比利·穆雷主演的优秀电影《问你的父母》——是一件坏事,但在你的计算机程序中使用loops
可能是一件伟大的事情。计算机程序的主要目的之一是日复一日地重复重复性的任务。我们用来奴役我们的程序并让它们执行这些乏味任务的方法之一就是所谓的循环。
正如您现在可能已经猜到的,当某个条件为true
时,循环会导致代码片段一遍又一遍地重复。就像条件语句一样(在第四章中介绍),循环需要满足或不满足一个条件,以便执行或不执行,这取决于程序员的需要。
有几种类型的循环,我们将在这非常冒险的一章中讨论每一种类型。所以准备好你自己吧,年轻的英雄——因为我们正准备变得疯狂!
什么是循环?
作为程序员,我们的总体目标之一是高效地编写代码。我们所做的一切都应该以提供良好的用户体验、减少处理器资源和用尽可能少的代码创建程序为中心。实现这一点的一种方法是使用循环,Python 中有两种类型的循环。正如本章介绍中所述,循环是一种神奇的生物,只要满足我们定义的条件,它就允许我们将一段代码重复任意次。
循环在编程中如何工作的一个例子是,如果你创建了一个应用,其中有人必须猜出你在想的数字。代码会一直让用户猜一个数字,直到他们猜对为止,这时循环会退出,程序的其余部分会执行。
一如既往,让我们进入不祥的危险房间!测试一些新的代码。首先,创建一个名为 SinisterLoop.py 的文件,并添加以下代码:
# Create an empty variable. We will store data in it later.
numberGuess = ''
# create a while loop that continues until the user enters the number 42
while numberGuess != '42':
print("Sinister Loop stands before you!")
print("I'll only let you capture me if you can guess the number in my brain!")
print("Enter a number between 0 and 4 gajillion:")
numberGuess = input() # Stores the number the user types into numberGuess
print("Sinister Loop screams in agony!")
print("How did you guess the number in his head was " + numberGuess + "?")
在这个代码片段的场景中,邪恶险恶的循环面对我们的英雄,神奇男孩,并迫使他猜测坏人心中的恶意数字。如果神奇小子成功了,邪恶循环将允许你抓住他。如果不是呢?好吧,如果不是,那么他会一遍又一遍地不停地让你输入一个数字。好玩吧。
在这个代码示例中,我们学到了一些新东西。我们首先做了一些迄今为止还没有做过的事情——我们创建了一个名为numberGuess
的空白(或空)变量。我们将这个变量留空,因为我们将让用户稍后用数据填充它。
接下来,我们创建一个称为while
循环的代码块。该行:
while numberGuess != '42':
告诉程序运行*,而变量numberGuess
的值不等于*或!=
为“42”。然后我们打印几行文本,最后请求用户输入一个数字。存储数字的实际行在代码中:
numberGuess = input()
input()函数类似于 print()函数,只是它接受来自用户的输入或数据。这种输入是通过用户键盘上的按键来收集的。这些击键存储在赋值操作符(=
)左边的变量中——在本例中是numberGuess
。
继续运行代码,输入不同的数字几次,最后输入数字 42,看看程序在运行。
都鬼混完了?很好。简要说明:在这个例子中,我们使用了不等于(!=
)操作符作为我们的while
标准。您可能会问自己,为什么我们没有使用等于或操作符。原因是因为我们希望程序循环——或者迭代——当某事不为真时。如果我们使用一个来代替,并要求程序在值等于 42 时循环,我们将会产生一个严重的循环逻辑错误。
这就是循环变得危险的地方。如果我们告诉程序在变量值等于 42 时循环,程序根本不会执行我们的循环。为什么呢?因为我们告诉它在 numberGuess 等于 42 时循环。但是,请记住:我们从不设置 numberGuess 的值。因此,当 Python 去检查值是否为 42 时,它确定它不是,并退出循环,因为它只会在值为 42 时循环!
如果您认为这很棘手,请考虑以下情况:如果我们将 numberGuess 的值设置为 42,并将 while 循环条件保持为==42,会发生什么情况?
在这种情况下,程序将永远循环下去。为什么呢?因为我们告诉它“当 numberGuess 的值是 42 时,遍历这段代码。”这就是众所周知的可怕的无限循环,它是每个程序员生存的祸根。为了好玩,让我们创建一个名为 InfiniteLoop.py 的新文件,并输入以下代码:
注意
当你运行这个程序时,会出现一个无限循环。退出它,你将不得不关闭你的空闲窗口,并重新启动空闲。
# Create a variable with the value of 42.
numberGuess = 42
print("Sinister Loop stands before you!")
print("Behold my infinite loop!")
# create a while loop that continues while the value of numberGuess is 42.
while numberGuess == 42:
print("Loop!")
运行代码看看会发生什么。恭喜——你创建了你的第一个无限循环!现在,再也不要这样做了!
让我们尝试一些不同的东西。让我们用文本代替数字来表示我们的值。创建另一个名为WonderBoyPassword.py
的新文件,并键入以下代码:
# create a variable to hold Wonder Boy's password
password = ''
print("Welcome to Optimal Dad's Vault of Gadgets!")
while password != "wonderboyiscool2018":
print("Please enter your password to access some fun tech!")
password = input()
print("You entered the correct password!")
print("Please take whatever gadgets you need!")
print("Don't touch the Doom Canon though - that belongs to Optimal Dad!")
这段代码的运行很像你所期望的那样。就像我们使用数字'42'
的例子一样,这个程序创建一个空变量并打印出一些介绍性的文本。然后我们创建一个while
循环,该循环被设置为运行,直到password
的值不等于到“wonderboyiscool2018”。一旦用户输入了这个特定的值,程序就退出循环,转到其他的print
语句。
然而,这里有一点小小的不同。因为我们使用的是文本而不是数字数据类型,所以输入的值必须与条件完全相同。也就是说,密码必须包含准确的文本“wonderboyiscool2018”。大写字母必须大写,小写字母必须小写。
这是为什么呢?不要陷入太多无聊的细节,要知道程序中的每个字符都有一个特定的赋值。记住,计算机看不到文本,而是一系列被翻译成机器语言的 1 和 0。正因为如此,计算机将“H”和“H”视为两个独立的事物。
运行该程序,并在提示时尝试键入“WonderBoyIsCool2018”或“WONDERBOYISCOOL2018”,然后观察会发生什么。
如你所见,程序继续while
循环,并不断要求输入密码。只有输入“wonderboyiscool2018”程序才会退出循环。
用这种类型的“循环逻辑”编写循环代码是完全正常的。事实上,当涉及到密码或安全信息时,这正是程序应该表现的方式。但是如果你不关心大写字母呢?如果您希望投入无论如何资本化都能发挥作用呢?
有几种方法可以实现这一点。其中之一是将文本转换成小写字母。为此,您可以使用一个名为 str.lower()的新字符串函数。更改 WonderBoyPassword.py 的代码,使其符合以下内容:
# create a variable to hold Wonder Boy's password
password = ''
print("Welcome to Optimal Dad's Vault of Gadgets!")
while password != "wonderboyiscool2018":
print("Please enter your password to access some fun tech!")
password = input()
password = password.lower()
print("You entered the correct password: ", password)
print("Please take whatever gadgets you need!")
print("Don't touch the Doom Canon though - that belongs to Optimal Dad!")
在这段代码中,我们在前面的代码片段中添加了新的一行:
password = password.lower()
这行代码获取变量password
中的数据,并将其转换成小写。这样,当循环检查密码是否正确时,它不需要担心用户是否输入了大写字母。
注意
要使整个字符串小写,可以使用str.lower()
。
例如:password.lower()
要使字符串大写,可以使用str.upper()
。
例如:password.upper()
极限环
虽然我们可以允许循环无限期地执行,但我们常常希望限制它们运行的次数。例如,在我们的WonderBoyPassword.py
代码中,我们允许用户想猜多少次就猜多少次;只有给出正确的密码,程序才会退出。然而,这可能不是编写这样一个程序的最佳方式。
当处理密码时——或者当您需要限制循环执行的次数时——您可以创建一个条件,使循环在满足给定标准时break
。
要查看使用中的break
,编辑WonderBoyPassword.py
中的代码,使其与以下代码匹配:
# create a variable to hold Wonder Boy's password
password = ''
passwordAttempt = 0
print("Welcome to Optimal Dad's Vault of Gadgets!")
while password != "wonderboyiscool2018":
print("Please enter your password to access some fun tech!")
password = input()
password = (password.lower())
passwordAttempt = passwordAttempt + 1
if password == "wonderboyiscool2018":
print("You entered the correct password: ", password)
print("Please take whatever gadgets you need!")
print("Don't touch the Doom Canon though - that belongs to Optimal Dad!")
elif passwordAttempt == 3:
print("Sorry, you are out of attempts!")
break
在这个版本的WonderBoyPassword.py
中,我们增加了几行新代码。首先,我们定义了一个名为passwordAttempt
的新变量,并赋予其值0
。该变量将用于跟踪猜测密码的尝试次数。每次用户猜错了,循环就会重复,多亏了这段代码:
passwordAttempt = passwordAttempt + 1
将1
加到passwordAttempt
的值上。然后我们添加了两个if
语句。如果用户猜出了正确的密码,第一个会打印出一些文本。一旦passwordAttempt
的值等于 3(尝试三次后),el if
语句就会触发。一旦被触发,它打印出一些道歉文本,然后使用break
语句退出while
循环。
试着输入几次密码,确保至少三次猜错密码,至少一次猜对密码。
对于循环
另一种确保循环只迭代一定次数的方法是使用for
循环。当您知道想要重复一段代码多少次时,通常会使用这种类型的循环。引入 for 循环的一种流行方法是创建一个程序,通过一系列数字进行计数——比如 1-10。然而,我们不是普通的程序员——我们是碰巧编码的超级英雄。因此,我们需要一种特殊类型的程序。看看邪恶的恶棍!Count10.py 的例子!
print("Sinister Loop, I know you are in there!")
print("If you don't come out of the cafeteria freezer by the time I count to 10...")
print("You won't get any of that delicious stop-sign shaped pizza!")
for x in range(1,11):
print(x)
print("I warned you! Now all the pizza belongs to Wonder Boy!")
这段代码的重要部分出现在这里:
for x in range(1,11):
print(x)
for
开始循环。'x'
是一个变量(你可以随意命名这个变量;传统上程序员将其命名为‘I’或‘x’),它们将保存迭代次数的值。事实上,当这样使用时,它被称为一个迭代变量。接下来,我们使用range
函数告诉循环要使用的序列。一个序列可以由一个数字范围组成,也可以使用文本(下面将详细介绍)。
range
后面括号中的数字是函数的start
和stop
参数。对于我们的例子,我们想数到 10,所以我们把开始放在 1,停止放在 11。我们在这里选择使用 11,尽管我们希望范围在 10 处停止,因为范围在我们的终点之前的数字处停止。如果我们想让阴险的循环有很长的时间从冰箱里出来,我们可以在 0 点开始,在 10 点停止,或者在 12 点开始,在 1,000,000 点停止。).
最后,我们print(x)
打印出迭代发生的次数。一旦到达‘10’,程序breaks
从 for 循环跳到代码的下一部分,这恰好是最后一条打印语句。
如果您运行该程序,您会得到以下结果:
Sinister Loop, I know you are in there!
If you don't come out of the cafeteria freezer by the time I count to 10...
You won't get any of that delicious stop-sign shaped pizza!
1
2
3
4
5
6
7
8
9
10
I warned you! Now all the pizza belongs to Wonder Boy!
如果我们想让代码更有趣一点,我们可以向属于for
循环的print
语句添加一些文本,如下所示:
print("Sinister Loop, I know you are in there!")
print("If you don't come out of the cafeteria freezer by the time I count to 10...")
print("You won't get any of that delicious stop-sign shaped pizza!")
for x in range(1,11):
print(x, "Mississippii")
print("I warned you! Now all the pizza belongs to Wonder Boy!")
我们所做的只是改变:
print(x)
到
print(x, "Mississippii")
这给了我们一个新的结果:
Sinister Loop, I know you are in there!
If you don't come out of the cafeteria freezer by the time I count to 10...
You won't get any of that delicious stop-sign shaped pizza!
1 Mississippii
2 Mississippii
3 Mississippii
4 Mississippii
5 Mississippii
6 Mississippii
7 Mississippii
8 Mississippii
9 Mississippii
10 Mississippii
I warned you! Now all the pizza belongs to Wonder Boy!
我们在这里所做的只是将单词“Mississippii”添加到迭代循环之外的输出中。
除了向上计数,range 还有向下计数的能力。为了实现这一点,我们需要使用一个叫做step
的东西。Step
是range()
的可选参数,用于向上或向下“步进”数字。例如,如果我们想从 10 倒数到 1,我们将编写一个如下所示的 For 循环:
for x in range(10,0, -1):
print(x)
循环的-1
部分是step
,基本上是告诉程序每次减一。如果您运行此代码,将会导致:
10
9
8
7
6
5
4
3
2
1
如果我们做了step -2
,倒计时会每次减 2。
for x in range (10,1 -2):
print(x)
那么结果将是:
10
8
6
4
2
如果我们想以 2 为增量递增计数,我们不需要添加+ 符号——我们只需将step
添加为2
,如下所示:
for x in range(1,10,2):
print(x)
这将产生:
1
3
5
7
9
For 循环更有趣
当然,打印出数字并不是我们使用for
循环实现的唯一事情。如上所述,任何时候我们知道我们想要循环通过代码的次数,一个for
循环是我们最好的选择。
例如,也许我们想变得令人讨厌,在屏幕上打印一大堆相同的文本。我们的朋友for
loop 可以帮上忙!
for x in range(1,10):
print("Wonder")
print("Boy!")
在退出循环并以“Boy!”结束之前,这个小片段将打印出文本“Wonder”九次。如果你把一些很酷的主题音乐放在后面,你就可以为你自己的电视连续剧做好准备了!
我们使用for
循环的另一种方式是遍历列表。假设我们有一个邪恶恶棍的列表,我们想打印出他们的名字。我们可以使用类似这样的代码:
nefariousVillains = ['Sinister Loop', 'The Pun-isher', 'Jack Hammer', 'Frost Bite', 'The Sequin Dream']
print("Here is a list of today's villains, brought to you by:")
print("Heroic Construction Company. You destroy the city, we make it almost, sort of new.")
print("Villains Most Vile:")
for villains in nefariousVillains:
print(villains)
在这里,我们创建了一个list
(我们最初在第三章中讨论过列表,你应该还记得)。然后我们用各种小人填充了list
。接下来,我们打印出一些文本,然后进行我们的for
循环:
for villains in nefariousVillains:
print(villains)
这一次,for
从创建一个变量名villains
开始,它的工作将是保存(临时)我们的list
中每个值的值。由于我们没有设置range
,循环将对nefariousVillains list
中的每个值执行一次。每次都会给villains
变量分配一个不同的值。例如,第一次通过循环时,'Sinister Loop'
被传递到villains
然后被打印。然后循环第二次继续,并通过'The Pun-isher'
到villains
,再次打印。这一直持续到循环运行完list
中的所有值。villains
中的最终值将是'The Sequin Dream'
。它的值将保持不变,直到您更改数据。
如果我们运行这段代码,结果将是:
Here is a list of today's villains, brought to you by:
Heroic Construction Company. You destroy the city, we make it almost, sort of new.
Villains Most Vile:
Sinister Loop
The Pun-isher
Jack Hammer
Frost Bite
The Sequin Dream
中断、继续和传递语句
尽管循环被用来遍历部分代码,但有时我们可能会发现我们需要一种方法来提前结束循环,跳过循环的一部分,或者处理一些不属于循环的数据。在这些努力中,有三个陈述可以帮助我们。
我们早先了解过break
;有了这个语句,我们可以在某些条件发生的情况下尽早退出循环。例如,在我们的WonderBoyPassword.py
程序中,我们使用break
在输入密码三次后退出程序。因为我们之前已经讨论过这个语句,所以让我们继续讨论continue
语句。
像break
语句一样,continue
语句让你跳过一个循环的一部分,而不是完全跳出它。考虑一下:如果你有一个从十开始倒数的程序,但是在中途你想打印一些文本;你可以通过continue
来实现这个目标。
让我们创建一个名为 DoomsdayClock.py 的新文件。在这个程序中,险恶循环已经启动了一个倒计时定时器,它将发出你的…嗯,厄运的信号。但是,反派总是那么啰嗦,如果他在倒计时的某个时刻有话要说,千万不要惊讶!
将此代码输入您的文件:
print("The nefarious Sinister Loop stands before you, greedily rubbing his hands together!")
print("He has his hand on a lever and has a large grin on his face.")
print("Sinister Loop opens his mouth and says:")
print("'You are doomed now Wonder Boy!'")
print("'You have ten seconds to live! Listen as I count down the time!'")
for x in range(10,0,-1):
print(x, "Mississippii!")
# When x is equal to 5, print some text, then continue with the count down.
if x==5:
print("'Any last words, Wonder Boy?!?'")
continue
print("You wait for your inevitable doom as the count reaches 0...")
print("But nothing happens!")
print("Sinister Loop screams, 'Foiled Again!'")
运行示例并观察结果,结果应该是这样的:
The nefarious Sinister Loop stands before you, greedily rubbing his hands together!
He has his hand on a lever and has a large grin on his face.
Sinister Loop opens his mouth and says:
'You are doomed now Wonder Boy!'
'You have ten seconds to live! Listen as I count down the time!'
10 Mississippii!
9 Mississippii!
8 Mississippii!
7 Mississippii!
6 Mississippii!
5 Mississippii!
'Any last words, Wonder Boy?!?'
4 Mississippii!
3 Mississippii!
2 Mississippii!
1 Mississippii!
You wait for your inevitable doom as the count reaches 0...
But nothing happens!
Sinister Loop screams, 'Foiled Again!'
这段代码像我们的其他for
循环一样工作,有一点例外。一旦程序命中我们的if
语句,它就会检查'x'
是否等于5
。由于我们将range
设置为以-1 的增量从 10 递减计数到 0,我们知道在代码重复第五次左右'x'
将等于 5。当它出现时,我们的条件得到满足,我们打印出文本“Any last words Wonder Boy?!?
”,有效地暂停了一会儿循环(实际上,我们跳过了一次迭代,以便我们可以打印一些文本),然后再次进入循环。
在continue
语句之后,程序完成其正常循环,然后正常退出程序。
如果您查看结果,请注意行'5 Mississippi'
从未打印出来。记住,这是因为我们跳过了循环,所以它不会打印那一行。
到目前为止,我们已经了解了如何在特定条件适用时退出循环,或者如何跳过循环中的一次迭代(分别使用break
和continue,
)。我们学到的下一个说法看起来没那么有用,但是,事实上,它确实在事物的大计划中服务于一个目的。
pass
语句在处理称为classes
的东西时特别有用——这是我们将在第八章讨论的主题。然而,就循环而言,pass 语句主要用作占位符。当你在计划一段代码,但不完全确定你的标准是什么时,这是一个很好的工具。
例如,在我们的DoomsdayClock.py
程序中,我们在循环中放置了一个 if 语句,以便在变量的值为 5 时执行一些文本。然而,如果我们不确定我们想要的文本是什么,或者在倒计时中我们想要将文本打印到哪里,该怎么办?也许我们在等待同事的反馈,然后不得不回到那段代码。
pass
语句可以让我们放置条件,而不用定义如果满足条件会发生什么,也不用担心因为没有完成代码而出错。这样,以后,当我们弄清楚我们希望在循环的这一部分发生什么时,我们可以在以后填充其余的代码。
如果我们将pass
语句插入到我们的DoomsdayClock.py
程序中,它看起来是这样的:
print("The nefarious Sinister Loop stands before you, greedily rubbing his hands together!")
print("He has his hand on a lever and has a large grin on his face.")
print("Sinister Loop opens his mouth and says:")
print("'You are doomed now Wonder Boy!'")
print("'You have ten seconds to live! Listen as I count down the time!'")
for x in range(10,0,-1):
print(x, "Mississippii!")
# When x is equal to 5, print some text, then continue with the count down.
if x==5:
pass
print("You wait for your inevitable doom as the count reaches 0...")
print("But nothing happens!")
print("Sinister Loop screams, 'Foiled Again!'")
如果您运行这段代码,您将会看到当到达if
语句时什么也没有发生——程序只是正常运行。然而,如果您要从语句中删除pass
,您将会收到一个错误,因为 Python 期望更多的代码来完成if
语句。自己试试看吧!
在这一集里!
我们在这一章里讲了很多,如果你觉得有点…糊涂,我不会责怪你。虽然这一章可能是迄今为止最难理解的,但好消息是,一旦你掌握了循环的使用,你就真的拥有了创建一些像样的真实世界程序所需的所有工具。
当然,你可能无法作为世界上最伟大的程序员——简称 WGP——走进办公室,得到一份高薪工作,但是,嘿,你还是个青少年;你已经远远领先于未来竞争的趋势。另外,别忘了,还有整整九章呢!
在这本书的这一点上,你应该对自己的涉猎和创建自己的代码片段和迷你程序感到舒适。像生活中的任何事情一样,熟能生巧,所以一定要经常测试你的新超能力。你编码得越多,你就越能理解编程。
说到这里,在下一章中,我们将会很好地运用我们到目前为止所学的一切,因为我们创建了我们的第一个完整的程序!它将被称为超级英雄生成器 3000,它将包含循环、变量、if-else 语句、字符串和数学函数等等;邀请你的朋友,你将是聚会的灵魂!
至于这一章,让我们在这一集参考页中快速回顾一下我们在中学到的内容!
-
如果满足/不满足给定的条件,循环允许您重复(也称为迭代)部分代码。
-
For 循环可用于在不满足条件时或通过使用 range 函数进行迭代。例如:
for x in range(1,10): print("Wonder Boy is here!")
-
Range()是一个函数,它允许你在一个循环中迭代一定的次数。它有三个参数,定义如下:
range(1, 10, 1)
第一个数字是起点。第二个数字是终点。第三个数字是可选的,称为步长,控制 range()计数的增量。例如,对步长使用 2 将在循环中每次迭代增加 2 个数字。
-
只要满足条件或标准,或者计算结果为布尔值 true,While 循环就会重复。例如:
salary = 0 while salary < 10: print("I owe, I owe, so off to work I go.") salary = salary +1
-
无限循环是有害的,大多数时候应该避免。当您的循环编程逻辑有缺陷或者犯了一个错误时,它们就会发生。它们是永无止境的循环——就像一堂糟糕的代数课。这里有一个例子(孩子们,不要对他这么做!):
x = 0
while x == 0:
print:("You down with L-O-O-P?")
print("Yeah, you know me!")
由于变量 x 等于 0,并且准则说当 x 等于 0 时循环,这个循环将永远继续下去。
-
Str.lower()是一个将字符串转换成小写的函数。例如:
name = "Wonder Boy" print(name.lower())
会用小写字母印刷“神奇小子”。
-
Str.upper()的工作方式与 str.lower()相同,只是它将字符串中的所有字母都改为大写。示例:
name = "wonder boy" print(name.upper())
-
如果满足某个条件,并且您希望循环提前结束,break 语句会强制循环退出(或中断)迭代。
-
continue 语句允许您跳过循环中的迭代,而不完全退出循环。
-
pass 语句是一种占位符,允许您创建循环,而不必在循环中定义某些条件,直到以后。通过这种方式,您可以创建循环结构,并决定以后的标准,而不会在测试代码时收到错误。
六、利用我们所学的知识
你已经走了很长一段路了。当你犯了一个不幸的错误,试图抓住他的微波比萨饼咬,你开始被一个放射性程序员咬。从那时起,你的力量开始绽放,你证明了自己是一个值得的伙伴。但是现在是真正考验你的知识和你的 l33t cod3r skillz 的时候了。你准备好迎接挑战了吗?
在这一章中,我们将回顾到目前为止你所学的一切,并将其用于创建你自己的全长程序。此外,你还将学习一些新的技巧,到本章结束时,你将从忠实的跟班升级为成熟的英雄。
你仍然是神奇小子,但至少你不用再给神奇爸爸擦鞋了!
创建你的第一个真正的程序
在我们开始创建我们的第一个全功能应用之前——我们将把它命名为超级英雄生成器 3000——我们必须首先了解我们到底希望程序做什么。基本概念很简单:我们想要一个应用,它会为我们随机生成一个超级英雄角色——没什么大不了的,对吧?
这是一个开始,但显然我们需要更多的细节。例如,什么是英雄?它们有什么属性吗?有超能力吗?名字怎么样?所有这些问题的答案都是肯定的。
作为优秀的、英勇的程序员,我们总是想计划好我们创建的任何程序。我们需要知道程序的目的,它将如何运行,以及在我们编码和构建它时有助于我们保持正轨的任何细节。
例如,我们知道在该计划中,我们将需要以下内容:
-
超级英雄名字(随机生成)
-
超级英雄姓氏(随机生成)
-
将超级英雄的名字/姓氏合并成一个字符串的代码
-
在给定范围内随机生成一组统计数据的代码。
-
随机发电机
此外,我们需要变量来保存我们所有的统计数据;我们的名、姓和组合名;还有我们的超能力。我们还需要一个数据结构——在本例中是lists
——来保存我们名字和超能力的值,我们将从中随机选择名字/能力给我们的英雄。
听起来很复杂?别担心,不会的。我们将一步一步地介绍计划的每一部分,让大家熟悉我们已经介绍过的所有内容。那就是说,让我们穿上斗篷和面具,开始超级英雄发电机 3000 的第一部分!
导入模块
首先,我们的程序将依赖于两个模块——一些预先存在的代码,用于执行一项我们可以用来节省时间和减少人为错误的常见任务。第一个是random
,我们已经用过了。提醒你一下,random
可以用来随机生成数字。它还允许您从列表中随机选择一个(或多个)值——等等。在我们的程序中,我们将它用于两个目的。
我们导入的第二个模块叫做time
,这是我们到目前为止还没有涉及到的。它的主要功能之一是允许我们在程序执行中创建一个“暂停”。您希望延迟一部分代码的执行可能有很多原因。出于我们的目的,我们使用time
来制造悬念,让程序看起来像是在计算复杂的东西。
让我们创建一个名为 SuperHeroGenerator3000.py 的新文件,并向其中添加以下代码:
# Importing the random module to use for randomizing numbers and strings later
import random
# Importing the time module to create a delay
import time
创造我们的变量
如前所述,这个程序将依赖于相当多的变量和列表来存储数据。为了保存 STATS(或统计)数据,我们将使用变量来满足我们的存储需求。现在,您应该熟悉它们的用法以及如何定义它们。也就是说,让我们将这段代码添加到我们的SuperHeroGenerator3000.py
文件中,就在我们导入time
和random
模块的下面:
brains = 0
braun = 0
stamina = 0
wisdom = 0
power = 0
constitution = 0
dexterity = 0
speed = 0
answer = ' '
第一组变量将用于保存统计数据,比如你的角色有多聪明,他们有多强壮,等等。请注意,初始值都设置为0
。在应用的后面,我们将使用random
来更改这些值。然而,就目前而言,我们必须给他们一个价值,所以0
就是这样!
您可能会注意到,我们有一个位于统计组之外的变量,名为 answer。一旦程序运行,它会问用户一个问题继续-我们将使用答案字符串变量来保存用户的回答。现在,我们没有给它赋值;用户的输入将在以后填充它。
定义我们的列表
列表用于保存多条数据。superHeroGenerator3000.py 应用依赖于三个列表:一个将保存可能的超级能力列表——命名的超级能力——而另外两个将保存可能的名字和姓氏列表。
在节目的后面,我们将使用随机从这些列表中选择值,给我们的英雄一个名字和超能力。现在,我们需要创建列表并给它们赋值。
现在,使用我提供的值。然而,在你测试了这个程序几次之后,你可以随意添加你自己古怪的名字组合和超级英雄能力到这些列表中——发挥创造力,玩得开心!
以下是列表的代码——将其添加到变量列表下的文件中:
# Creating a list of possible super powers
superPowers = ['Flying', 'Super Strength', 'Telepathy', 'Super Speed', 'Can Eat a Lot of Hot Dogs', 'Good At Skipping Rope']
# Creating lists of possible first and last names
superFirstName = ['Wonder','Whatta','Rabid','Incredible', 'Astonishing', 'Decent', 'Stupendous', 'Above-average', 'That Guy', 'Improbably']
superLastName = ['Boy', 'Man', 'Dingo', 'Beefcake', 'Girl', 'Woman', 'Guy', 'Hero', 'Max', 'Dream', 'Macho Man','Stallion']
现在我们已经有了数据结构,是时候进入代码的下一部分了。
介绍性文本和接受用户输入
我们代码的下一部分旨在问候用户并接受他们的一些输入。正如我们在第五章中了解到的,我们可以通过使用input()
函数接受用户的输入。将以下代码添加到您的文件中,就在您新创建的列表的下面:
# Introductory text
print("Are you ready to create a super hero with the Super Hero Generator 3000?")
# Ask the user a question and prompt them for an answer
# input() 'listens' to what they type on their keyboard
# We then use upper() to change the users answer to all uppercase letters
print("Enter Y/N:")
answer = input()
answer = answer.upper())
为了使生活更容易,在我们接受用户输入后,我们将他们的answer
转换成全部大写字母。我们为什么要这样做?以使我们在他们回答时不必检查小写和大写的组合。如果我们没有将文本全部转换为大写,我们将不得不检查“是”、“是”、“是”、“是”等等。转换字符串并检查一个简单的“是”(或者在本例中是“Y”)要容易得多,也更有效。
当answer
的值不等于为“是”时,我们通过使用重复的while
循环来检查用户的答案。一旦条件满足,循环退出,程序继续,乐趣才真正开始!
将while
循环添加到代码中,就在介绍性文本和input()
部分的下面:
# While loop to check for the answer "Y"
# This loop will continue while the value of answer IS NOT "Y"
# Only when the user types "Y" will the loop exit and the program continue
while answer != "Y":
print("I'm sorry, but you have to choose Y to continue!")
print("Choose Y/N:")
answer = input()
answer = answer.upper())
print("Great, let's get started!")
制造悬念!
就像在真实的写作中,有时在我们的计算机编程中,我们想要戏剧性地添加悬念或暂停,以使用户认为一些真正酷的事情正在发生。或者我们可能希望间歇地暂停一个程序,给用户时间阅读屏幕上的文本,而不是让它滚动得太快。
无论是哪种情况,我们都可以通过使用一个你还没有学会的新模块来实现这种戏剧性的效果:时间()。
虽然我们将在代码中使用 time(),但我们还不会涵盖整个函数——因为现在我们只想使用这个方便的新工具的一个方面,那就是利用它的sleep
函数。
像任何其他函数一样,时间接受参数——六个常用参数和一些不常用的参数。睡眠使你的程序暂停,以秒计算,在我们看来是这样的:
时间.睡眠(3)
括号中的数字是您想要暂停的秒数。我们可以键入并完成它,但是——如前所述——我们需要一些戏剧性的天赋!因此,我们不想单独使用 time.sleep(),而是想在用户屏幕上打印一些省略号(…)来模拟等待时间。只是看起来更酷!
为此,我们将把 time()函数放在一个重复三次的 for 循环中。每次通过循环,我们的程序将打印到用户的屏幕上。
将此代码添加到您的。py 文件:
print("Randomizing name...")
# Creating suspense using the time() function
for i in range(3):
print("...........")
time.sleep(3)
print("(I bet you can't stand the suspense!)")
print("")
理论上,如果我们在此时运行我们的程序,我们将在屏幕上看到以下输出:
Are you ready to create a super hero with the Super Hero Generator 3000?
Enter Y/N:
y
Great, let's get started!
Randomizing name...
...........
...........
...........
(I bet you can't stand the suspense!)
当time()
功能启动时,每个“…………”打印一行正好需要 3 秒钟,创造了我们的“戏剧性停顿”
既然我们已经有了介绍性的文本,了解了如何在程序中暂停或产生停顿,并且已经有了初始变量/列表——以及我们导入的模块——是时候进入应用的核心部分了!
在下一节中,我们将创建代码的一部分,随机生成超级英雄的所有不同部分。为此,我们依赖于黄金旧random()
模块。
随机选择超级英雄的名字
每个超级英雄都需要五样东西:
-
很酷的服装
-
超级大国
-
无害的收入来源,使他们永远不会被人看到白天工作
-
纸巾擦去所有那些孤独的微波晚餐的眼泪(超级英雄没时间约会!)
-
当然,还有一个很棒的名字
超级发电机 3000 代码的下一步是对名称生成部分进行编程。之前,您可能还记得,我们创建了两个充满超级英雄名字和姓氏的列表。提醒一下,以下是这些列表:
superFirstName = ['Wonder','Whatta','Rabid','Incredible', 'Astonishing', 'Decent', 'Stupendous', 'Above-average', 'That Guy', 'Improbably']
superLastName = ['Boy', 'Man', 'Dingo', 'Beefcake', 'Girl', 'Woman', 'Guy', 'Hero', 'Max', 'Dream', 'Macho Man','Stallion']
我们的名字生成部分代码背后的想法是,我们想从这两个列表中各取一个名字,并将它们合并成一个,创建我们的英雄的名字。有许多方法可以实现这一点,但就我们的目的而言,我们希望随机选择这两个值——这样,每次程序运行时,它都会创建一个唯一的名称组合。
在深入研究之前,让我们先看看实现这种效果的代码。将以下代码添加到您的SuperHeroGenerator3000.py
文件中,就在time()
代码的下面:
# Randomizing Super Hero Name
# We do this by choosing one name from each of our two name lists
# And adding it to the variable superName
superName = random.choice(superFirstName)+ " " +random.choice(superLastName)
print("Your Super Hero Name is:")
print(superName)
这段代码非常容易理解。我们首先创建一个名为superName
的变量,它的任务是保存我们英雄的姓和名的组合(从列表superFirstName
和SuperLastName
中获得)。
接下来,我们使用 random()——特别是 random . choice——从我们的列表superFirstName
中随机选择一个值,从superLastName
中随机选择一个值。
代码行的这一部分内容如下:
+ " " +
可能看起来令人困惑;然而,它的目的很简单。在这种情况下,+
符号被用来连接,或者将我们的两个字符串加在一起。因为我们希望名字和姓氏之间有一个空格,所以我们也必须通过在中间添加" "
来添加或者连接一个空格。否则,我们可以只写random.choice(superFirstName) + random.choice(superLastName).
最后,我们通过使用:print(superName)打印出新创建的 superName 的值来完成程序的这一部分。
现在,如果我们运行我们的程序,它会产生类似这样的结果:
Are you ready to create a super hero with the Super Hero Generator 3000?
Enter Y/N:
y
Great, let's get started!
Randomizing name...
...........
...........
...........
(I bet you can't stand the suspense!)
Your Super Hero Name is:
Improbably Max
或者
Are you ready to create a super hero with the Super Hero Generator 3000?
Enter Y/N:
y
Great, let's get started!
Randomizing name...
...........
...........
...........
(I bet you can't stand the suspense!)
Your Super Hero Name is:
Stupendous Hero
注意
因为这些值是随机生成的,你的超级英雄的名字可能会与我提供的例子不同。
快速入住
在我们继续下一步之前,让我们检查一下你的代码是否与我的匹配。如果您一直按照正确的顺序编写代码,您的程序应该如下所示。如果没有,不用担心——只需修改您的代码以匹配我的代码,并重新阅读这些部分以找出哪里出错了!
下面是您的代码目前应该呈现的样子:
# Importing the random module to use for randomizing numbers and strings later
import random
# Importing the time module to create a delay
import time
# Creating - or initializing - our variables that will hold character stats
brains = 0
braun = 0
stamina = 0
wisdom = 0
power = 0
constitution = 0
dexterity = 0
speed = 0
answer = ''
# Creating a list of possible super powers
superPowers = ['Flying', 'Super Strength', 'Telepathy', 'Super Speed', 'Can Eat a Lot of Hot Dogs', 'Good At Skipping Rope']
# Creating lists of possible first and last names
superFirstName = ['Wonder','Whatta','Rabid','Incredible', 'Astonishing', 'Decent', 'Stupendous', 'Above-average', 'That Guy', 'Improbably']
superLastName = ['Boy', 'Man', 'Dingo', 'Beefcake', 'Girl', 'Woman', 'Guy', 'Hero', 'Max', 'Dream', 'Macho Man','Stallion']
# Introductory text
print("Are you ready to create a super hero with the Super Hero Generator 3000?")
# Ask the user a question and prompt them for an answer
# input() 'listens' to what they type on their keyboard
# We then use upper() to change the users answer to all uppercase letters
print("Enter Y/N:")
answer = input()
answer = (answer.upper())
# While loop to check for the answer "Y"
# This loop will continue while the value of answer IS NOT "Y"
# Only when the user types "Y" will the loop exit and the program continue
while answer != "Y":
print("I'm sorry, but you have to choose Y to continue!")
print("Choose Y/N:")
answer = input()
answer = answer.upper())
print("Great, let's get started!")
print("Randomizing name...")
# Creating suspense using the time() function
for i in range(3):
print("...........")
time.sleep(3)
print("(I bet you can't stand the suspense!)")
print("")
# Randomizing Super Hero Name
# We do this by choosing one name from each of our two name lists
# And adding it to the variable superName
superName = random.choice(superFirstName)+ " " +random.choice(superLastName)
print("Your Super Hero Name is:")
print(superName)
随机分配超能力
现在有趣的部分来了——随机产生我们英雄的超能力!毕竟,如果他不能在不到一天的时间里从鼻子里射出激光束或者长出一把完整的胡子,他就不会那么超级了,不是吗?
就像我们的superFirstName
和superLastName
列表一样,你会记得我们已经创建了一个拥有超能力的列表,恰当地命名为superPowers
。正是从这个列表中,我们将选择我们的超级英雄在他的武器库中拥有什么力量。
注意
在我们完成整个程序并且你已经测试了几次之后,请随意将你自己的超能力组合添加到superPowers
列表中——尽情享受,尽可能地发挥创造力!
将以下代码添加到您的superHeroGenerator3000.py
文件中,直接放在随机生成您的英雄名字的代码部分的下面:
print("")
print("Now it's time to see what super power you have!)")
print("(generating super hero power...)")
# Creating dramatic effect again
for i in range(2):
print("...........")
time.sleep(3)
print("(nah...you wouldn't like THAT one...)")
for i in range(2):
print("...........")
time.sleep(3)
print("(almost there....)")
# Randomly choosing a super power from the superPowers list
# and assigning it to the variable power
power = random.choice(superPowers)
# Printing out the variable power and some text
print("Your new power is:")
print(power)
print("")
正如您所看到的,这段代码首先将一些文本打印到用户的屏幕上,通知他们英雄的超能力即将产生。在这之后,我们使用time.sleep()
不是一次,而是两次,以创造更戏剧性的效果并减慢程序速度。这一次,通过我们的for
循环,我们每次只打印两行.......
——每行持续 3 秒钟。
代码的下一部分:
power = random.choice(superPowers)
创建一个名为power
的新变量,然后从superPowers
列表中给它分配一个随机值。最后,这段代码通过打印出power
的值来结束,这样用户就可以看到选择了什么样的超级能力。
从理论上讲,如果我们现在运行这个程序,我们将会得到类似如下的结果:
Are you ready to create a super hero with the Super Hero Generator 3000?
Enter Y/N:
y
Great, let's get started!
Randomizing name...
...........
...........
...........
(I bet you can't stand the suspense!)
Your Super Hero Name is:
Astonishing Dingo
Now it's time to see what super power you have!)
(generating super hero power...)
...........
...........
(nah...you wouldn't like THAT one...)
...........
...........
(almost there....)
Your new power is:
Flying
或者
Are you ready to create a super hero with the Super Hero Generator 3000?
Enter Y/N:
y
Great, let's get started!
Randomizing name...
...........
...........
...........
(I bet you can't stand the suspense!)
Your Super Hero Name is:
Astonishing Stallion
Now it's time to see what super power you have!)
(generating super hero power...)
...........
...........
(nah...you wouldn't like THAT one...)
...........
...........
(almost there....)
Your new power is:
Can Eat a Lot of Hot Dogs
请记住,您的结果可能会有所不同,因为超能力和超级英雄的名字是随机生成的。
结束我们的节目
我们几乎完成了创建您的第一个完整的程序!用无与伦比的斯坦·李的话说——精益求精!
我们应用的最后一部分将随机生成我们英雄的统计数据。您可能还记得,在我们代码的开始,我们创建了七个变量(brains, braun, stamina, wisdom, constitution, dexterity
和speed
),并给每个变量赋值0
。
在下面的代码中,我们将为这七个变量中的每一个赋予一个从 1 到 20 的随机整数值。我们使用在第二章中讨论过的random.randint()
函数来实现。
将以下内容添加到您的superHeroGenerator3000.py
文件中:
print("Last but not least, let's generate your stats!")
print("Will you be super smart? Super strong? Super Good Looking?")
print("Time to find out!")
# Creating dramatic effect and slowing the program down again
for i in range(3):
print("...........")
time.sleep(3)
# Randomly filling each of the below variables with a new value
# The new values will range from 1-20
brains = random.randint(1,20)
braun = random.randint(1,20)
stamina = random.randint(1,20)
wisdom = random.randint(1,20)
constitution = random.randint(1,20)
dexterity = random.randint(1,20)
speed = random.randint(1,20)
# Printing out the statistics
print("Your new stats are:")
print("")
print("Brains: ", brains)
print("Braun: ", braun)
print("Stamina: ", stamina)
print("Wisdom: ", wisdom)
print("Constitution: ", constitution)
print("Dexterity: ", dexterity)
print("Speed: ", speed)
print("")
# Printing out a full summary of the generated super hero
# This includes the hero's name, super power, and stats
print("Here is a summary of your new Super Hero!")
print("Thanks for using the Super Hero Generator 3000!")
print("Tell all your friends!")
print("")
print("Character Summary:")
print("")
print("")
print("Super Hero Name: ", superName)
print("Super Power: ", power)
print("")
print("Brains: ", brains)
print("Braun: ", braun)
print("Stamina: ", stamina)
print("Wisdom: ", wisdom)
print("Constitution: ", constitution)
print("Dexterity: ", dexterity)
print("Speed: ", speed)
如果我们检查新代码的这一部分:
brains = random.randint(1,20)
braun = random.randint(1,20)
stamina = random.randint(1,20)
wisdom = random.randint(1,20)
constitution = random.randint(1,20)
dexterity = random.randint(1,20)
speed = random.randint(1,20)
我们可以看到给变量随机赋值是多么容易。括号中的数字代表允许范围的最低值和允许的最高值;该数字将始终介于 1 和 20 之间。
超级发电机 3000 代码-完成!
现在是时候享受我们第一个完整项目的荣耀了!拍拍自己的背,跑去告诉你所有的朋友,我是一个多么伟大的老师,这本书是自奶酪切片以来最好的东西!我在骗谁——大块的奶酪也一样棒!
我们需要做的最后一件事是确保您的代码与本书中的内容完全匹配。一旦我们这样做了,你就可以自由地反复运行这个程序,改变列表的值,并邀请你所有的朋友和老师来生成他们自己的超级英雄!
以下是superHeroGenerator3000.py
的完整代码——比较您的代码并确保其匹配:
# Importing the random module to use for randomizing numbers and strings later
import random
# Importing the time module to create a delay
import time
# Creating - or initializing - our variables that will hold character stats
brains = 0
braun = 0
stamina = 0
wisdom = 0
power = 0
constitution = 0
dexterity = 0
speed = 0
answer = ''
# Creating a list of possible super powers
superPowers = ['Flying', 'Super Strength', 'Telepathy', 'Super Speed', 'Can Eat a Lot of Hot Dogs', 'Good At Skipping Rope']
# Creating lists of possible first and last names
superFirstName = ['Wonder','Whatta','Rabid','Incredible', 'Astonishing', 'Decent', 'Stupendous', 'Above-average', 'That Guy', 'Improbably']
superLastName = ['Boy', 'Man', 'Dingo', 'Beefcake', 'Girl', 'Woman', 'Guy', 'Hero', 'Max', 'Dream', 'Macho Man','Stallion']
# Introductory text
print("Are you ready to create a super hero with the Super Hero Generator 3000?")
# Ask the user a question and prompt them for an answer
# input() 'listens' to what they type on their keyboard
# We then use upper() to change the users answer to all uppercase letters
print("Enter Y/N:")
answer = input()
answer = answer.upper())
# While loop to check for the answer "Y"
# This loop will continue while the value of answer IS NOT "Y"
# Only when the user types "Y" will the loop exit and the program continue
while answer != "Y":
print("I'm sorry, but you have to choose Y to continue!")
print("Choose Y/N:")
answer = input()
answer = answer.upper())
print("Great, let's get started!")
print("Randomizing name...")
# Creating suspense using the time() function
for i in range(3):
print("...........")
time.sleep(3)
print("(I bet you can't stand the suspense!)")
print("")
# Randomizing Super Hero Name
# We do this by choosing one name from each of our two name lists
# And adding it to the variable superName
superName = random.choice(superFirstName)+ " " +random.choice(superLastName)
print("Your Super Hero Name is:")
print(superName)
print("")
print("Now it's time to see what super power you have!)")
print("(generating super hero power...)")
# Creating dramatic effect again
for i in range(2):
print("...........")
time.sleep(3)
print("(nah...you wouldn't like THAT one...)")
for i in range(2):
print("...........")
time.sleep(3)
print("(almost there....)")
# Randomly choosing a super power from the superPowers list
# and assigning it to the variable power
power = random.choice(superPowers)
# Printing out the variable power and some text
print("Your new power is:")
print(power)
print("")
print("Last but not least, let's generate your stats!")
print("Will you be super smart? Super strong? Super Good Looking?")
print("Time to find out!")
# Creating dramatic effect and slowing the program down again
for i in range(3):
print("...........")
time.sleep(3)
# Randomly filling each of the below variables with a new value
# The new values will range from 1-20
brains = random.randint(1,20)
braun = random.randint(1,20)
stamina = random.randint(1,20)
wisdom = random.randint(1,20)
constitution = random.randint(1,20)
dexterity = random.randint(1,20)
speed = random.randint(1,20)
# Printing out the statistics
print("Your new stats are:")
print("")
print("Brains: ", brains)
print("Braun: ", braun)
print("Stamina: ", stamina)
print("Wisdom: ", wisdom)
print("Constitution: ", constitution)
print("Dexterity: ", dexterity)
print("Speed: ", speed)
print("")
# Printing out a full summary of the generated super hero
# This includes the hero's name, super power, and stats
print("Here is a summary of your new Super Hero!")
print("Thanks for using the Super Hero Generator 3000!")
print("Tell all your friends!")
print("")
print("Character Summary:")
print("")
print("")
print("Super Hero Name: ", superName)
print("Super Power: ", power)
print("")
print("Brains: ", brains)
print("Braun: ", braun)
print("Stamina: ", stamina)
print("Wisdom: ", wisdom)
print("Constitution: ", constitution)
print("Dexterity: ", dexterity)
print("Speed: ", speed)
当您运行这个程序时,您应该会看到类似于下面的结果,请记住,超级英雄的名字、超能力和属性都是不同的,因为它们都是随机生成的——我知道,我听起来像一张破唱片!
可能的结果:
Are you ready to create a super hero with the Super Hero Generator 3000?
Enter Y/N:
y
Great, let's get started!
Randomizing name...
...........
...........
...........
(I bet you can't stand the suspense!)
Your Super Hero Name is:
Wonder Man
Now it's time to see what super power you have!)
(generating super hero power...)
...........
...........
(nah...you wouldn't like THAT one...)
...........
...........
(almost there....)
Your new power is:
Good At Skipping Rope
Last but not least, let's generate your stats!
Will you be super smart? Super strong? Super Good Looking?
Time to find out!
...........
...........
...........
Your new stats are:
Brains: 8
Braun: 13
Stamina: 5
Wisdom: 15
Constitution: 20
Dexterity: 11
Speed: 9
Here is a summary of your new Super Hero!
Thanks for using the Super Hero Generator 3000!
Tell all your friends!
Character Summary:
Super Hero Name: Wonder Man
Super Power: Good At Skipping Rope
Brains: 8
Braun: 13
Stamina: 5
Wisdom: 15
Constitution: 20
Dexterity: 11
Speed: 9
七、利用函数、模块和内置功能节省时间
现在我们已经正式创建了我们的第一个成熟的 Python 应用(如果你想跳过的话,回到第六章)!),是时候开始学习如何真正利用我们的编程能力,尽可能成为最好的程序员了。
到目前为止,在本书中,我们已经提到了尽可能高效地使用代码的重要性。编码不仅有效地增加了我们一天可以完成的工作量,它还有其他几个好处。首先,它有助于确保我们的程序使用尽可能少的内存和处理能力,其次,它有助于减少代码中的错误数量。后者之所以能够实现,自然是因为我们输入的越少,输入错误或出现编程逻辑或语法错误的机会就越少。
高效工作的一部分包括在我们创建新程序时反复重用经过测试和验证的代码片段。这些代码通常是为了执行常见的任务而编写的,可以是几行简单的代码,也可以是几千行。然而,关键的一点是,我们知道它们是可行的,我们可以简单地将它们保存在自己的小文件中,并在需要时将其导入到我们的程序中,而不是一遍又一遍地输入所有的代码,这为我们节省了大量的时间和错误。
以这种方式使用时,这些代码片段被称为模块。简单来说,模块就是包含代码的文件。就这样。
到目前为止,我们已经在本书中使用了几个模块,包括时间和随机。在这一章中,我们不仅要学习如何创建我们自己的模块,还要看看 Python 提供的一些更流行和最常用的模块。毕竟,Python 内置的大量经过实践检验的真正的 Python 模块——以及由大型 Python 社区创建的模块——是 Python 成为如此强大和重要的编程语言的原因之一!
所以,放下那些美味的玉米味薯片,擦掉手指上的奶酪粉(一定不要沾到新的漂亮斗篷上!)并准备进一步扩展您的编程能力,因为我们将深入研究任何超级英雄程序员的终极武器——模块!
定义模块
现在我们知道了模块是什么,您可能会发现自己想知道一个模块到底可以包含什么。从我们之前的定义出发,一个模块可以包含任何代码。它可能有一组函数,可能是一个将一串文本写到用户屏幕上的脚本,可能包含一个变量列表,甚至可能是几行将其他模块导入到程序中的代码。
只要是 Python 文件(。py)并包含代码,它是一个模块。
从技术上讲,Python 中有三种类型的模块。它们是:
-
内置的
-
包装
-
自定义/定制创建
内置的
内置指的是已经是 Python 库的标准部分的模块和函数。当您执行 Python 安装时,这些模块是预安装的。它们包括一些有用的函数,比如datetime
(允许您处理日期和时间数据类型)、random
(用于随机生成数字)和SocketServer
(用于创建网络服务器框架)。
你已经熟悉了一些内置的,因为我们在本书的例子中已经使用了它们。有相当多的内置模块是 Python 的标配。要查看完整的名单,可以访问: https://docs.python.org/3.7/py-modindex.html
。但是,请注意,这个列表会随着每个版本而变化,所以在访问 Python 时,请务必检查您正在使用的 Python 版本。org 网站。
当然,查看内置 Python 模块列表的一个更简单的方法是简单地使用以下代码:
# Print a list of Python Built-in Modules
print(help("modules”))
当您运行这段代码时,Python 会打印出您当前已经安装的所有内置模块的列表,如下所示:
请稍候,我正在收集所有可用模块的列表…
BooleanExamples _testmultiphase gettext reprlib
BooleanLogic _thread glob rlcompleter
ConditionalStatements _threading_local grep rpc
Count10 _tkinter gzip rstrip
DoomsdayClock _tracemalloc hashlib run
Example1 _warnings heapq runpy
InfiniteLoop _weakref help runscript
LearningText _weakrefset help_about sched
ListExample _winapi history scrolledlist
LogicalOperatorsExample abc hmac search
MathIsHard aifc html searchbase
MultipleElifs antigravity http searchengine
OrExample argparse hyperparser secrets
PowersWeaknesses array idle select
RandomGenerator ast idle_test selectors
...
当然,看到内置列表是很好的,但是更好的是知道它们实际上是做什么的,而不必登录到互联网上用谷歌搜索它们。幸运的是,Python 有两个内置功能可以帮助解决这个问题!
第一个是.__doc__
——也称为文档字符串或文档字符串。您遇到的每个模块都应该有一个 docstring 作为其定义的一部分,它基本上服务于该函数或模块的用途的“文档”。要读取模块的文档,我们可以按以下方式调用这个 docstring:
# First we must import the module
import time
# Then we can print out its documentation
print (time.__doc__)
您希望查看其文档的模块名称位于.__doc__
命令之前。
如果您将该代码放在一个文件中并运行它,您的结果将如下所示:
This module provides various functions to manipulate time values.
There are two standard representations of time. One is the number
of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer
or a floating point number (to represent fractions of seconds).
The Epoch is system-defined; on Unix, it is generally January 1st, 1970.
The actual value can be retrieved by calling gmtime(0).
The other representation is a tuple of 9 integers giving local time.
The tuple items are:
year (including century, e.g. 1998)
month (1-12)
day (1-31)
hours (0-23)
minutes (0-59)
seconds (0-59)
weekday (0-6, Monday is 0)
Julian day (day in the year, 1-366)
DST (Daylight Savings Time) flag (-1, 0 or 1)
If the DST flag is 0, the time is given in the regular time zone;
if it is 1, the time is given in the DST time zone;
if it is -1, mktime() should guess based on the date and time.
另一个选项是查看文档——事实上,您可能希望同时使用这两个选项,因为这两个命令的文档可能是不同的。例如,如果您输入以下代码:
# First we must import the module
import time
# Then we can print out its documentation using our second method
help(time)
并运行它,您将得到一个不同的、比您使用.__doc__
时更冗长的响应:
Help on built-in module time:
NAME
time - This module provides various functions to manipulate time values.
DESCRIPTION
There are two standard representations of time. One is the number
of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer
or a floating point number (to represent fractions of seconds).
The Epoch is system-defined; on Unix, it is generally January 1st, 1970.
The actual value can be retrieved by calling gmtime(0).
The other representation is a tuple of 9 integers giving local time.
The tuple items are:
year (including century, e.g. 1998)
month (1-12)
day (1-31)
hours (0-23)
minutes (0-59)
seconds (0-59)
weekday (0-6, Monday is 0)
Julian day (day in the year, 1-366)
DST (Daylight Savings Time) flag (-1, 0 or 1)
If the DST flag is 0, the time is given in the regular time zone;
if it is 1, the time is given in the DST time zone;
if it is -1, mktime() should guess based on the date and time.
这个结果实际上只是将要打印的整个文档的一小部分。
要了解区别,请尝试同时使用两者。将这段代码输入到一个名为printDocumentation.py
的新 Python 文件中并运行它,检查结果以查看不同之处:
# First we must import the module whose documentation we wish to view
import time
# Printing documentation using .__doc__ or docstring
print (time.__doc__)
# Creating a dividing line so that we can see where the next set of
# Documentation begins.
print("Here is what using HELP looks like...")
print("######################################")
# Printing documentation using help()
help(time)
这段代码的结果太大了,无法包含在本书中,但是您可以自己运行这个程序来查看所有的文档。请务必记下哪个文档属于我们用来读取 docstring 的哪个方法。
包装
在导入模块之前,您必须首先安装它——也就是说,如果它没有预打包在您的 Python 安装中。我们可以用来安装一个非标准包(或由社区开发的包)的一种方法是使用一个名为pip
的内置功能。pip
在 Python 的大多数当前版本中是自动安装的,所以除非您使用的是该语言的遗留版本,否则您应该已经准备好了。
pip
是 Python 及更高版本附带的安装程序。要使用该程序,您必须启动您的命令行窗口(您可以通过访问开始,然后运行,然后键入 CMD 来完成)。从那里,您可以通过在命令提示符下键入“pip”来查看可能的pip
命令列表。
现在,您只需要理解一个简单的 pip 命令:install。然而在我们使用它之前,我们总是想检查我们是否已经安装了我们想要安装的包。
为此,我们返回到 IDLE 并键入:
import <nameofmodule>
例如,如果我们想查看是否安装了时间模块,我们可以键入:
import time
如果我们收到一个错误,我们知道那个特定的模块还没有安装。
为了解决这个问题,我们回到我们的命令行——或 CMD——并安装模块。对于我们的例子,让我们使用Pygame
包,它是一个流行的包,有助于视频游戏开发(我们将在后面的章节中讨论这个主题)。
在命令提示符下,只需输入:
python -m pip install Pygame
几秒钟后,命令行将开始下载和安装软件包的过程。一旦完成,您将看到类似于图 7-1 的消息。
图 7-1
恭喜你!您现在已经安装了您的第一个 Python 包!
创建您自己的模块
使用预先存在的内置模块和包是使程序更高效、更不容易出错的好方法。另一个你可以用来节省时间和键盘敲击的工具是创建你自己的模块,你可以反复使用。
创建我们的模块的第一部分是创建一个我们可以从另一个程序中调用或引用的函数。对于这个练习,我们需要两个 Python 文件。我们将从创建主程序将使用的实际模块开始。
创建一个文件called ourFirstModule.py
并输入以下代码:
# Define your function using def
def firstFunction():
print("This is our first function!")
保存文件并尝试运行它。虽然您可以看到程序确实执行了,但似乎什么也没发生。这是因为我们只定义了我们的函数将要做什么,但是我们还没有调用它,调用它,或者告诉它做任何事情。
为了实际使用这个函数,我们必须从另一个文件中调用它。
创建另一个名为testingModule.py
的文件,并输入以下代码:
# We first have to import our module
# We import our module by using the name of the file, minus the .py extension
import ourFirstModule
# Now we call the function to use it
ourFirstModule.firstFunction()
运行该文件时,您应该会看到以下结果:
This is our first function!
祝贺您,您已经创建了您的第一个模块,并成功地从另一个程序中调用了它!
当然,模块中可以有多个函数,所以让我们再添加几个函数,并在我们的文件中练习调用它们。打开备份您的ourFirstModule.py
文件并编辑代码,如下所示:
# Define your function
def firstFunction():
print("This is our first function!")
# Define a second function
def secondFunction():
print("Look, a second function!")
# Define a variable
a = 2+3
接下来,我们需要编辑我们的testingModule.py
文件,以利用我们新定义的函数和变量。修改代码,使其如下所示:
# We first have to import our module
# We import our module by using the name of the file, minus the .py extension
import ourFirstModule
# Now we call the function to use it
ourFirstModule.firstFunction()
# Calling our second function
ourFirstModule.secondFunction()
# Calling and printing a variable within our module
print("The value of a is: ",ourFirstModule.a)
除了调用不是一个而是两个函数之外,这段代码还打印出了名为a
的变量的值。我们使用代码print(ourFirstModule.a)
来实现这一点。部分ourFirstModule
引用ourFirstModule.py
文件并告诉 Python 从哪里提取函数,而.a
告诉它打印什么变量。例如,如果我们的变量被命名为lastName
,它应该是这样的:print(ourFirstModule.lastName)
。
最后,对于我们创建的任何代码,我们总是希望确保记录我们的工作。之前,我们使用了.__doc__
和help()
来打印模块的文档。现在,我们将使用多行注释(或三组)来创建我们自己的文档。
打开您的ourFirstModule.py
文件,修改第一个函数firstFunction()
的代码,添加以下注释:
# Define your function
def firstFunction():
""" This is the documentation - or docstring - for firstFunction()
We can put examples of use here or just document what the function is for
That way future programmers - or ourselves later on - can read the
"helpfile" for our firstFunction and know what it was intended for
"""
print("This is our first function!")
第一组缩进的"""
和第二组缩进的"""
之间的所有内容都被认为是注释或文档,如前一章所讨论的。
现在,打开您的testingModule.py
文件,让我们向其中添加以下代码,以便打印出文档:
# print the helpfile for firstFunction()
help(ourFirstModule)
您可以将这段代码放在文件中的任何地方,但是我选择将它直接放在打印 firstFunction 的 print()函数下面。
运行该程序,您应该会看到以下结果:
This is our first function!
Help on module ourFirstModule:
NAME
ourFirstModule - # Define your function
FUNCTIONS
firstFunction()
This is the documentation - or docstring - for firstFunction()
We can put examples of use here or just document what the function is for
That way future programmers - or ourselves later on - can read the
"helpfile" for our firstFunction and know what it was intended for
secondFunction()
DATA
a = 5
Look, a second function!
The value of a is: 5
常见内置功能
Python 有很多很棒的内置功能,到目前为止,我们已经在本书中讨论了很多。但是就像一个可靠的多用途皮带中的物品一样,你手头永远不会有太多的工具。当然,一罐防鲨剂可能看起来很可笑,但是等你和那个能屏住呼吸,哦,是的,还能和鲨鱼说话的人打一场仗。你觉得防鲨剂有多傻?
内置功能近 70 个,大部分你作为程序员在生活中都会用到。现在,我们将讨论一些到目前为止我们已经跳过的更常见的问题。我们将按类别处理它们,从字符串函数开始。
字符串函数
正如您可能猜到的,字符串函数是处理字符串的函数。我们已经介绍了一些,包括str.upper()
和str.lower()
,它们分别将字符串转换成大写和小写。
此外,实际上使一个字符串大写或小写,你也可以执行检查,看看字符串的内容实际上是什么情况。例如,您可能想知道用户是否输入了全部大写字母。要进行检查,您可以使用以下代码:
# Create a string of all uppercase letters
testString = "I AM YELLING!"
print("Is the user yelling?")
# Check to see if the value of testString consists of all uppercase letters
print(testString.isupper())
在这种情况下,我们使用名为 str.isupper()的字符串函数来检查字符串是否包含大写字母。如果您要运行这段代码,您将得到一个布尔响应(真或假):
Is the user yelling?
True
请注意,如果字符串中的任何字符是小写的,它将返回一个False
值,因为该函数正在检查整个字符串是否包含大写字母。
如果我们想检查一下是否是小写,我们可以使用字符串函数 str.islower(),如下所示:
# Create a string of all uppercase letters
testString = "I AM YELLING!"
print("Is the user yelling?")
# Check to see if the value of testString consists of all uppercase letters
print(testString.islower())
当然,在本例中,它将返回一个False
。
有时候我们可能想要检查用户输入的是什么类型的字符。例如,如果用户在填写表单,我们想知道他们的名字和姓氏,我们不希望他们输入数值——除非他们是机器人或外星人,请注意。
要检查一个字符串是否只包含字母(没有数字),您可以使用str.isalpha()
:
# Create a string to check if the variable only contains letters
firstName = "James8"
# Check to see if the value of firstName contains any numbers
print("Does your name contain any letters?")
if firstName.isalpha() == False:
print("What are you, a robot?")
由于字符串firstName
的值不仅仅包含字母(它包含一个数字),那么if
返回一个False
值,导致print()
函数打印出它的文本:
Does your name contain any numbers?
What are you, a robot?
如果firstName
中只有包含字母字符(A-Z 和 A-Z),那么if
将返回True
,并且不会打印任何内容。
我们还可以检查这些值是只有数字还是只包含数字。例如,我们可能希望确保某人没有在社会保险或电话号码字段中输入字母。为了检查字符串中只有数字的值,我们使用函数str.isnumeric()
:
# Create a string to check if the variable only contains numbers
userIQ = "2000"
# Check to see if the value if userIQ contains only numbers and no letters
if userIQ.isnumeric() == False:
print("Numbers only please!")
else:
print("Congrats, you know the difference between a number and a letter!")
同样,我们检查userIQ
是否只包含数字的评估结果是True
还是False
。由于userIQ
只包含数字——没有字母——结果为真,我们得到结果:
Congrats, you know the difference between a number and a letter!
我们还可以检查我们的字符串是否只包含空格——也称为空白。为此,我们使用函数str.isspace()
:
# Check to see if the value of UserIQ contains all spaces or whitespace characters
if userIQ.isspace() == True:
print("Please enter a value other than a bunch of spaces you boob!")
由于userIQ
不包含所有空格,所以什么都不会发生。如果只有空格,Python 就会执行我们定义的 print()函数。
我们可以使用的另一个有用的字符串函数是len()
,它让我们计算一个字符串中的字符数。你可能会问自己,“我到底为什么要这么做?”答案很简单:您可能希望限制变量中的字符数,比如密码,或者确保它有足够的字符。
又或许,你和我一样有强迫症(强迫症),觉得什么都要数。我认为这是我很多很多超能力中的一个…
要计算字符串中的字符数,您可以使用类似如下的代码:
# Create a variable to count the number of characters it holds using len()
testPassword = "MyPasswordIsPassword!"
当您运行此代码时,您将得到以下结果:
21
数字函数
现在我们已经学习了一些新的字符串函数,让我们继续处理数字。我们之前检查了几个帮助我们处理数字的函数,以及让我们执行漂亮的数学方程而不伤害我们大脑(无论如何,太多)的运算符。
让我们的大脑更擅长数字(不要告诉你的英语老师这是我写的!),让我们看看更多的函数,它们将提升我们的编程技能,并使我们看起来像众所周知的火箭科学家。
有时当我们和数字打交道时,我们会被要求告诉我们的老板哪个数字比所有其他数字都高。为了找出一系列数字中的最大值,我们使用max()
。
# Create a list containing a group of numbers
studentGrades = [100, 90, 80, 70, 60, 50, 0]
# Use max() to find the highest number in the studentGrades list
print("What is the highest grade in the studentGrades list?")
print:("Answer :")
print(max(studentGrades))
如果我们运行这段代码,将会导致:
What is the highest grade in the studentGrades list?
100
因为100
是我们列表中 studentGrades 的最高值。如果我们想找出一系列数字的最小值,我们可以使用 min():
# Create a list containing a group of numbers
studentGrades = [100, 90, 80, 70, 60, 50, 0]
# Use max() to find the highest number in the studentGrades list
print("What is the highest grade in the studentGrades list?")
print:("Answer :")
print(max(studentGrades))
# Use min() to find the lowest number in the studentGrades list
print("What is the lowest grade in the studentGrades list?")
print:("Answer :")
print(min(studentGrades))
运行后,该代码输出:
What is the highest grade in the studentGrades list?
100
What is the lowest grade in the studentGrades list?
0
我们也可以使用min()
和max()
而不创建列表。要单独使用它们,您应该键入:
print(min(100, 90, 80, 70, 60, 50, 0))
print(max(100, 90, 80, 70, 60, 50, 0))
注意
您还可以在字符串上使用 min()和 max(),例如,在从 a 到 z 排列的字母表上使用 min 将返回“a”,而使用 max()将返回“z”。
另一种常见的做法是对给定列表中的所有数字求和。也许你需要计算你公司的工资总额或工作时间。为此,您可以使用sum()
函数。让我们用下面的代码来总结一下:
# Create another list containing more numbers, representing payroll
totalPayroll = [500, 600, 200, 400, 1000]
# Use sum() to calculate the sum of the numbers in a list
print("How much did we pay employees this week?")
print("The total payroll was: ")
print(sum(totalPayroll))
此示例的输出将是:
How much did we pay employees this week?
The total payroll was:
2700
练习你的新函数
我们在你的超级英雄编程实用带上增加了很多新函数。现在是时候实践你所学的知识来提高你的技能了。在下文中,你会发现一个我们学过的新的字符串函数列表和一个我们在这一章中摆弄过的新的数字/数学函数列表。
您可以随意输入这些代码,并找出新的令人兴奋的方法来使用这些简单而强大的函数。
字符串函数示例
# Create a string of all uppercase
letters
testString = "I am YELLING!"
# Create a string to check if the variable only contains letters
firstName = "James8"
# Create a string to check if the variable only contains numbers
userIQ = "2000"
# Create a variable to count the number of characters it holds using len()
testPassword = "MyPasswordIsPassword!"
# A series of functions are tested below
print("Is the user yelling?")
# Check to see if the value of testString consists of all uppercase letters
print(testString.isupper())
# Check to see if the value of firstName contains any numbers
print("Does your name contain any numbers?")
if firstName.isalpha() == False:
print("What are you, a robot?")
# Check to see if the value if userIQ contains only numbers and no letters
if userIQ.isnumeric() == False:
print("Numbers only please!")
else:
print("Congrats, you know the difference between a number and a letter!")
# Check to see if the value of UserIQ contains all spaces or whitespace characters
if userIQ.isspace() == True:
print("Please enter a value other than a bunch of spaces you boob!")
# Count the number of characters in a password
print("Let's see how many characters are in testPassword!")
print("I count: ")
print(len(testPassword))
数字函数示例
# Create a list containing a group of numbers
studentGrades = [100, 90, 80, 70, 60, 50, 0]
# Create another list containing more numbers, representing payroll
totalPayroll = [500, 600, 200, 400, 1000]
# Use max() to find the highest number in the studentGrades list
print("What is the highest grade in the studentGrades list?")
print:("Answer :")
print(max(studentGrades))
# Use min() to find the lowest number in the studentGrades list
print("What is the lowest grade in the studentGrades list?")
print:("Answer :")
print(min(studentGrades))
# Use min() and max() without defining a list
print(min(100, 90, 80, 70, 60, 50, 0))
print(max(100, 90, 80, 70, 60, 50, 0))
# Use sum() to calculate the sum of the numbers in a list
print("How much did we pay employees this week?")
print("The total payroll was: ")
print(sum(totalPayroll))
在这一集里!
这一集太壮观了!太神奇了!太惊人了!这是蜘蛛…好吧,让我们只是说这是不可思议的,就这样吧(嘿,那些大的漫画公司不拥有这些话!).
在这一章中,你真的在你的编程能力上向前迈进了一大步,学习了如何创建你自己的模块和函数。通过学习更多的内置功能,您甚至能够使用 Python 最强大的组件之一——社区创建的包。
我们讨论了很多,所以,一如既往,这里是我们在这一章中添加到你的超能力工具包中的一些好东西的总结!
-
有三种类型的模块:内置模块、软件包模块和自定义模块。
-
Python 中预装了内置包,包是由第三方供应商/Python 社区创建的,自定义包是您自己创建的包。
-
帮助()和。doc help 打印模块的文档或帮助文件:
示例:帮助(时间)和打印(时间。doc)
-
帮助(“模块”)列出了您的 Python 安装当前必须提供的所有可用模块。
-
import 将模块导入到程序中。
示例:导入时间
-
您可以在命令行上使用 pip 安装软件包:
python -m pip 安装
-
def 用于定义一个函数。
Example:
def firstFunction(): print("Hello!")
-
str.upper()和 str.lower()分别将字符串转换为大写和小写。
-
str.isalpha、str.isnumeric 和 str.isspace()都检查是否使用了正确的数据类型。
-
len()计算字符串中的字符数。
-
min()和 max()在数字或字符串值列表中查找最小值和最大值。
-
sum()计算列表中包含的值的总和。