Python从入门到实战学习笔记(二)
第 5 章 if
语句
在Python中,if
语句让你能够检查程序的当前状态,并采取相应的措施。
5.1 条件测试
每条if
语句的核心都是一个值为True
或False
的表达式,这种表达式称为条件测试 。Python根据条件测试的值为True
还是False
来决定是否执行if
语句中的代码。如果条件测试的值为True
,Python就执行紧跟在if
语句后面的代码;如果为False
,Python就忽略这些代码。
(1)检查是否相等
大多数条件测试将一个变量的当前值同特定值进行比较。最简单的条件测试检查变量的值是否与特定值相等.
❶ >>> car = 'bmw'
❷ >>> car == 'bmw'True
这个相等运算符 在两边的值相等时返回True
,否则返回False
。在本例中,两边的值相等,因此Python返回True
。一个等号是陈述,两个等号则是发问.
(2)检查是否相等时忽略大小写
在Python中检查是否相等时区分大小写。如果大小写很重要,这种行为有其优点。但如果大小写无关紧要,只想检查变量的值,可将变量的值转换为小写,再进行比较.
>>> car = 'Audi'
>>> car.lower() == 'audi'
True
(3)检查是否不相等
要判断两个值是否不等,可结合使用惊叹号和等号(!=
),其中的惊叹号表示不 ,其他很多编程语言中也是如此。
如果这两个值不相等,Python将返回True
,进而执行紧跟在if
语句后面的代码;如果相等,Python将返回False
,因此不执行紧跟在if
语句后面的代码。编写的大多数条件表达式检查两个值是否相等,但有时候检查两个值是否不等的效率更高。
requested_topping = 'mushrooms'❸ if requested_topping != 'anchovies':print("Hold the anchovies!")
(4)数值比较
条件语句中可包含各种数学比较,如小于、小于等于、大于、大于等于:
>>> age = 19
>>> age < 21
True
>>> age <= 21
True
>>> age > 21
False
>>> age >= 21
False
(5)检查多个条件
你可能想同时检查多个条件。例如,有时候需要在两个条件都为True
时才执行相应的操作,而有时候只要求一个条件为True
。在这些情况下,关键字and
和or
可助你一臂之力。
①使用and
检查多个条件
要检查是否两个条件都为True
,可使用关键字and
将两个条件测试合而为一。如果每个测试都通过了,整个表达式就为True
;如果至少一个测试没有通过,整个表达式就为False
。
❸ >>> age_0 = 22>>> age_1 = 18
❷ >>> age_0 >= 21 and age_1 >= 21False
❸ >>> age_1 = 22>>> age_0 >= 21 and age_1 >= 21True
②使用or检查多个条件
关键字or
也能够让你检查多个条件,但只要至少一个条件满足,就能通过整个测试。仅当两个测试都没有通过时,使用or
的表达式才为False
。
❶ >>> age_0 = 22>>> age_1 = 18
❷ >>> age_0 >= 21 or age_1 >= 21True
❸ >>> age_0 = 18>>> age_0 >= 21 or age_1 >= 21False
(6)检查特定值是否包含在列表中
要判断特定的值是否已包含在列表中,可使用关键字in
。
>>> requested_toppings = ['mushrooms', 'onions', 'pineapple']
❶ >>> 'mushrooms' in requested_toppingsTrue
❷ >>> 'pepperoni' in requested_toppingsFalse
在❶处和❷处,关键字in
让Python
检查列表requested_toppings
是否包含'mushrooms'
和'pepperoni'
。这种技术很有用,让你能够在创建一个列表后,轻松地检查其中是否包含特定的值。
(7)检查特定值是否不包含在列表中
还有些时候,确定特定的值未包含在列表中很重要。在这种情况下,可使用关键字not in
。
banned_users = ['andrew', 'carolina', 'david']user = 'marie'❶ if user not in banned_users:print(f"{user.title()}, you can post a response if you wish.")
(8)布尔表达式
随着你对编程的了解越来越深入,将遇到术语布尔表达式 ,它不过是条件测试的别名。与条件表达式一样,布尔表达式的结果要么为True
,要么为False
。
5.2 if
语句
(1)简单的if
语句
最简单的if
语句只有一个测试和一个操作:
if conditional_test:do something
第一行可包含任何条件测试,而在紧跟在测试后面的缩进代码块中,可执行任何操作。如果条件测试的结果为True
,Python就会执行紧跟在if
语句后面的代码,否则Python将忽略这些代码。
在if
语句中,缩进的作用与在for
循环中相同。如果测试通过了,将执行if
语句后面所有缩进的代码行,否则将忽略它们。在紧跟if
语句后面的代码块中,可根据需要包含任意数量的代码行。
(2)if-else
语句
我们经常需要在条件测试通过时执行一个操作,在没有通过时执行另一个操作。在这种情况下,可使用Python提供的if-else
语句。if-else
语句块类似于简单的if
语句,但其中的else
语句让你能够指定条件测试未通过时要执行的操作。
(3)if-elif-else
结构
我们经常需要检查超过两个的情形,为此可使用Python提供的if-elif-else
结构。Python只执行if-elif-else
结构中的一个代码块。它依次检查每个条件测试,直到遇到通过了的条件测试。测试通过后,Python将执行紧跟在它后面的代码,并跳过余下的测试。
age = 12❶ if age < 4:print("Your admission cost is $0.")
❷ elif age < 18:print("Your admission cost is $25.")
❸ else:print("Your admission cost is $40.")
(4)使用多个elif
代码块
可根据需要使用任意数量的elif
代码块。
(5)省略else
代码块
Python并不要求if-elif
结构后面必须有else
代码块。在有些情况下,else
代码块很有用;而在其他一些情况下,使用一条elif
语句来处理特定的情形更清晰
age = 12if age < 4:price = 0elif age < 18:price = 25elif age < 65:price = 40
❶ elif age >= 65:price = 20print(f"Your admission cost is ${price}.")
else
是一条包罗万象的语句,只要不满足任何if
或elif
中的条件测试,其中的代码就会执行。这可能引入无效甚至恶意的数据。如果知道最终要测试的条件,应考虑使用一个elif
代码块来代替else
代码块。这样就可以肯定,仅当满足相应的条件时,代码才会执行。
(6)测试多个条件
if-elif-else
结构功能强大,但仅适合用于只有一个条件满足的情况:遇到通过了的测试后,Python就跳过余下的测试。这种行为很好,效率很高,让你能够测试一个特定的条件。
然而,有时候必须检查你关心的所有条件。在这种情况下,应使用一系列不包含elif
和else
代码块的简单if
语句。在可能有多个条件为True
且需要在每个条件为True
时都采取相应措施时,适合使用这种方法。
❶ requested_toppings = ['mushrooms', 'extra cheese']❷ if 'mushrooms' in requested_toppings:print("Adding mushrooms.")
❸ if 'pepperoni' in requested_toppings:print("Adding pepperoni.")
❹ if 'extra cheese' in requested_toppings:print("Adding extra cheese.")print("\nFinished making your pizza!")结果:
Adding mushrooms.
Adding extra cheese.Finished making your pizza!
如果修改一下:
requested_toppings = ['mushrooms', 'extra cheese']if 'mushrooms' in requested_toppings:print("Adding mushrooms.")
elif 'pepperoni' in requested_toppings:print("Adding pepperoni.")
elif 'extra cheese' in requested_toppings:print("Adding extra cheese.")print("\nFinished making your pizza!")结果:
Adding mushrooms.Finished making your pizza!
总之,如果只想执行一个代码块,就使用
if-elif-else
结构;如果要执行多个代码块,就使用一系列独立的if
语句。
5.3 使用if
语句处理列表
通过结合使用if
语句和列表,可完成一些有趣的任务:对列表中特定的值做特殊处理;高效地管理不断变化的情形,如餐馆是否还有特定的食材;证明代码在各种情形下都将按预期那样运行。
requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']for requested_topping in requested_toppings:
❶ if requested_topping == 'green peppers':print("Sorry, we are out of green peppers right now.")
❷ else:print(f"Adding {requested_topping}.")print("\nFinished making your pizza!")Adding mushrooms.
Sorry, we are out of green peppers right now.
Adding extra cheese.Finished making your pizza!
这里在比萨中添加每种配料前都进行检查。❶处的代码检查顾客是否点了青椒。如果是,就显示一条消息,指出不能点青椒的原因。❷处的else
代码块确保其他配料都将添加到比萨中。
(1)确定列表不是空的
到目前为止,我们对于处理的每个列表都做了一个简单的假设——假设它们都至少包含一个元素。因为马上就要让用户来提供存储在列表中的信息,所以不能再假设循环运行时列表不是空的。有鉴于此,在运行for
循环前确定列表是否为空很重要。
❶ requested_toppings = []❷ if requested_toppings:for requested_topping in requested_toppings:print(f"Adding {requested_topping}.")print("\nFinished making your pizza!")
❸ else:print("Are you sure you want a plain pizza?")
首先创建一个空列表,其中不包含任何配料(见❶)。❷处进行简单的检查,而不是直接执行for
循环。在if
语句中将列表名用作条件表达式时,Python将在列表至少包含一个元素时返回True
,并在列表为空时返回False
。如果requested_toppings
不为空,就运行与前一个示例相同的for
循环;否则,就打印一条消息,询问顾客是否确实要点不加任何配料的原味比萨(见❸)。
(2)使用多个列表
❶ available_toppings = ['mushrooms', 'olives', 'green peppers','pepperoni', 'pineapple', 'extra cheese']❷ requested_toppings = ['mushrooms', 'french fries', 'extra cheese']❸ for requested_topping in requested_toppings:
❹ if requested_topping in available_toppings:print(f"Adding {requested_topping}.")
❺ else:print(f"Sorry, we don't have {requested_topping}.")print("\nFinished making your pizza!")Adding mushrooms.
Sorry, we don't have french fries.
Adding extra cheese.Finished making your pizza!
5.4 设置if
语句的格式
本章的每个示例都展示了良好的格式设置习惯。在条件测试的格式设置方面,PEP 8提供的唯一建议是,在诸如==
、>=
和<=
等比较运算符两边各添加一个空格。这样的空格不会影响Python对代码的解读,而只是让代码阅读起来更容易。
第 6 章 字典
字典可存储的信息量几乎不受限制,因此我们会演示如何遍历字典中的数据。另外,你还将学习存储字典的列表、存储列表的字典和存储字典的字典。
理解字典后,就能够更准确地为各种真实物体建模。你可以创建一个表示人的字典,然后想在其中存储多少信息就存储多少信息:姓名、年龄、地址、职业,以及能描述他的任何方面。你还能够存储任意两种相关的信息,如一系列单词及其含义,一系列人名及其喜欢的数,以及一系列山脉及其海拔,等等。
6.1 一个简单的字典
alien_0 = {'color': 'green', 'points': 5}print(alien_0['color'])
print(alien_0['points'])green
5
6.2 使用字典
在Python中,字典 是一系列键值对 。每个键 都与一个值相关联,你可使用键来访问相关联的值。与键相关联的值可以是数、字符串、列表乃至字典。事实上,可将任何Python对象用作字典中的值。在Python中,字典用放在花括号({}
)中的一系列键值对表示,如前面的示例所示.
键值对 是两个相关联的值。指定键时,Python将返回与之相关联的值。键和值之间用冒号分隔,而键值对之间用逗号分隔。在字典中,想存储多少个键值对都可以。
(1)访问字典中的值
要获取与键相关联的值,可依次指定字典名和放在方括号内的键,如下所示:
alien_0 = {'color': 'green'}
print(alien_0['color'])green
(2)添加键值对
字典是一种动态结构,可随时在其中添加键值对。要添加键值对,可依次指定字典名、用方括号括起的键和相关联的值。
alien_0 = {'color': 'green', 'points': 5}print(alien_0)❶ alien_0['x_position'] = 0
❷ alien_0['y_position'] = 25print(alien_0){'color': 'green', 'points': 5}
{'color': 'green', 'points': 5, 'y_position': 25, 'x_position': 0}
注意 在Python 3.7中,字典中元素的排列顺序与定义时相同。如果将字典打印出来或遍历其元素,将发现元素的排列顺序与添加顺序相同。
(3)先创建一个空字典
在空字典中添加键值对有时候可提供便利,而有时候必须这样做。为此,可先使用一对空花括号定义一个字典,再分行添加各个键值对。
alien_0 = {}alien_0['color'] = 'green'
alien_0['points'] = 5print(alien_0)alien_0 = {}{'color': 'green', 'points': 5}
(4)修改字典中的值
要修改字典中的值,可依次指定字典名、用方括号括起的键,以及与该键相关联的新值。
alien_0 = {'color': 'green'}
print(f"The alien is {alien_0['color']}.")alien_0['color'] = 'yellow'
print(f"The alien is now {alien_0['color']}.")The alien is green.
The alien is now yellow.
(5)删除键值对
对于字典中不再需要的信息,可使用del
语句将相应的键值对彻底删除。使用del
语句时,必须指定字典名和要删除的键。
alien_0 = {'color': 'green', 'points': 5}print(alien_0)❶ del alien_0['points']print(alien_0){'color': 'green', 'points': 5}
{'color': 'green'}
注意 删除的键值对会永远消失。
(6)由类似对象组成的字典
在前面的示例中,字典存储的是一个对象(游戏中的一个外星人)的多种信息,但你也可以使用字典来存储众多对象的同一种信息。
favorite_languages = {'jen': 'python','sarah': 'c','edward': 'ruby','phil': 'python',}❶ language = favorite_languages['sarah'].title()print(f"Sarah's favorite language is {language}.")Sarah's favorite language is C.
如你所见,我们将一个较大的字典放在了多行中。每个键都是一个被调查者的名字,而每个值都是被调查者喜欢的语言。确定需要使用多行来定义字典时,要在输入左花括号后按回车键。在下一行缩进四个空格,指定第一个键值对,并在它后面加上一个逗号。此后再按回车键时,文本编辑器将自动缩进后续键值对,且缩进量与第一个键值对相同。
定义好字典后,在最后一个键值对的下一行添加一个右花括号,并缩进四个空格,使其与字典中的键对齐。一种不错的做法是,在最后一个键值对后面也加上逗号,为以后在下一行添加键值对做好准备。
注意 对于较长的列表和字典,大多数编辑器提供了以类似方式设置格式的功能。对于较长的字典,还有其他一些可行的格式设置方式,因此在你的编辑器或其他源代码中,你可能会看到稍微不同的格式设置方式。
(7)使用get()
来访问值
使用放在方括号内的键从字典中获取感兴趣的值时,可能会引发问题:如果指定的键不存在就会出错。就字典而言,可使用方法get()
在指定的键不存在时返回一个默认值,从而避免这样的错误。方法get()
的第一个参数用于指定键,是必不可少的;第二个参数为指定的键不存在时要返回的值,是可选的:
alien_0 = {'color': 'green', 'speed': 'slow'}point_value = alien_0.get('points', 'No point value assigned.')
print(point_value)No point value assigned.
如果指定的键有可能不存在,应考虑使用方法get()
,而不要使用方括号表示法。
注意 调用
get()
时,如果没有指定第二个参数且指定的键不存在,Python将返回值None
。这个特殊值表示没有相应的值。None
并非错误,而是一个表示所需值不存在的特殊值,第8章将介绍它的其他用途。
6.3 遍历字典
一个Python字典可能只包含几个键值对,也可能包含数百万个键值对。鉴于字典可能包含大量数据,Python支持对字典进行遍历。字典可用于以各种方式存储信息,因此有多种遍历方式:可遍历字典的所有键值对,也可仅遍历键或值。
(1)遍历所有键值对
user_0 = {'username': 'efermi','first': 'enrico','last': 'fermi',}❶ for key, value in user_0.items():
❷ print(f"\nKey: {key}")
❸ print(f"Value: {value}")Key: username
Value: efermiKey: first
Value: enricoKey: last
Value: fermi
(2)遍历字典中的所有键
在不需要使用字典中的值时,方法keys()
很有用。
favorite_languages = {'jen': 'python','sarah': 'c','edward': 'ruby','phil': 'python',}❶ for name in favorite_languages.keys():print(name.title())
❶处的代码行让Python提取字典favorite_languages
中的所有键,并依次将它们赋给变量name
。输出列出了每个被调查者的名字。遍历字典时,会默认遍历所有的键。因此,如果将上述代码中for循环语句改为:for name in favorite_languages,输出不变。
方法keys()
并非只能用于遍历:实际上,它返回一个列表,其中包含字典中的所有键。
(3)按特定顺序遍历字典中的所有键
从Python 3.7起,遍历字典时将按插入的顺序返回其中的元素。要以特定顺序返回元素,一种办法是在for
循环中对返回的键进行排序。为此,可使用函数sorted()
来获得按特定顺序排列的键列表的副本.
favorite_languages = {'jen': 'python','sarah': 'c','edward': 'ruby','phil': 'python',}for name in sorted(favorite_languages.keys()):print(f"{name.title()}, thank you for taking the poll.")Edward, thank you for taking the poll.
Jen, thank you for taking the poll.
Phil, thank you for taking the poll.
Sarah, thank you for taking the poll.
(4)遍历字典中的所有值
如果主要对字典包含的值感兴趣,可使用方法values()
来返回一个值列表,不包含任何键。
favorite_languages = {'jen': 'python','sarah': 'c','edward': 'ruby','phil': 'python',}print("The following languages have been mentioned:")
for language in favorite_languages.values():print(language.title())The following languages have been mentioned:
Python
C
Ruby
Python
这种做法提取字典中所有的值,而没有考虑是否重复。涉及的值很少时,这也许不是问题,但如果被调查者很多,最终的列表可能包含大量重复项。为剔除重复项,可使用集合(set)。集合 中的每个元素都必须是独一无二的.通过对包含重复元素的列表调用set()
,可让Python找出列表中独一无二的元素,并使用这些元素来创建一个集合。
❶ for language in set(favorite_languages.values()):print(language.title())The following languages have been mentioned:
Python
C
Ruby
注意 可使用一对花括号直接创建集合,并在其中用逗号分隔元素:
>>> languages = {'python', 'ruby', 'python', 'c'}
>>> languages
{'ruby', 'python', 'c'}
集合和字典很容易混淆,因为它们都是用一对花括号定义的。当花括号内没有键值对时,定义的很可能是集合。不同于列表和字典,集合不会以特定的顺序存储元素。
6.4 嵌套
有时候,需要将一系列字典存储在列表中,或将列表作为值存储在字典中,这称为嵌套 。你可以在列表中嵌套字典、在字典中嵌套列表甚至在字典中嵌套字典。
(1)字典列表
alien_0 = {'color': 'green', 'points': 5}alien_1 = {'color': 'yellow', 'points': 10}alien_2 = {'color': 'red', 'points': 15}❶ aliens = [alien_0, alien_1, alien_2]for alien in aliens:print(alien){'color': 'green', 'points': 5}
{'color': 'yellow', 'points': 10}
{'color': 'red', 'points': 15}
(2)在字典中存储列表
有时候,需要将列表存储在字典中,而不是将字典存储在列表中。
# 存储所点比萨的信息。
❶ pizza = {'crust': 'thick','toppings': ['mushrooms', 'extra cheese'],}# 概述所点的比萨。
❷ print(f"You ordered a {pizza['crust']}-crust pizza ""with the following toppings:")❸ for topping in pizza['toppings']:print("\"f+topping)You ordered a thick-crust pizza with the following toppings:mushroomsextra cheese
每当需要在字典中将一个键关联到多个值时,都可以在字典中嵌套一个列表。
❶ favorite_languages = {'jen': ['python', 'ruby'],'sarah': ['c'],'edward': ['ruby', 'go'],'phil': ['python', 'haskell'],}❷ for name, languages in favorite_languages.items():print(f"\n{name.title()}'s favorite languages are:")
❸ for language in languages:print(f"\t{language.title()}")Jen's favorite languages are:PythonRubySarah's favorite languages are:CEdward's favorite languages are:RubyGoPhil's favorite languages are:PythonHaskell
注意 列表和字典的嵌套层级不应太多。如果嵌套层级比前面的示例多得多,很可能有更简单的解决方案。
(4)在字典中存储字典
可在字典中嵌套字典,但这样做时,代码可能很快复杂起来。
users = {'aeinstein': {'first': 'albert','last': 'einstein','location': 'princeton',},'mcurie': {'first': 'marie','last': 'curie','location': 'paris',},}❶ for username, user_info in users.items():
❷ print(f"\nUsername: {username}")
❸ full_name = f"{user_info['first']} {user_info['last']}"location = user_info['location']❹ print(f"\tFull name: {full_name.title()}")print(f"\tLocation: {location.title()}")Username: aeinsteinFull name: Albert EinsteinLocation: PrincetonUsername: mcurieFull name: Marie CurieLocation: Paris
请注意,表示每位用户的字典都具有相同的结构。虽然Python并没有这样的要求,但这使得嵌套的字典处理起来更容易。倘若表示每位用户的字典都包含不同的键,for
循环内部的代码将更复杂。
第 7 章 用户输入和while
循环
7.1 函数input()
的工作原理
函数input()
让程序暂停运行,等待用户输入一些文本。获取用户输入后,Python将其赋给一个变量,以方便你使用。
message = input("Tell me something, and I will repeat it back to you: ")
print(message)Tell me something, and I will repeat it back to you: Hello everyone!
Hello everyone!
函数input()
接受一个参数——要向用户显示的提示 (prompt)或说明,让用户知道该如何做。在本例中,Python运行第一行代码时,用户将看到提示Tell me something, and I will repeat it back to you:
。程序等待用户输入,并在用户按回车键后继续运行。输入被赋给变量message
,接下来的print(message)
将输入呈现给用户。
7.2 while
循环
for
循环用于针对集合中的每个元素都执行一个代码块,而while
循环则不断运行,直到指定的条件不满足为止。
要立即退出while
循环,不再运行循环中余下的代码,也不管条件测试的结果如何,可使用break
语句。
注意 在任何Python循环中都可使用
break
语句。例如,可使用break
语句来退出遍历列表或字典的for
循环。
(1)在循环中使用continue
要返回循环开头,并根据条件测试结果决定是否继续执行循环,可使用continue
语句,它不像break
语句那样不再执行余下的代码并退出整个循环。
current_number = 0while current_number < 10:
❶ current_number += 1if current_number % 2 == 0:continueprint(current_number)1
3
5
7
9
if
语句检查current_number
与2的求模运算结果。如果结果为0(意味着current_number
可被2整除),就执行continue
语句,让Python忽略余下的代码,并返回循环的开头。如果当前的数不能被2整除,就执行循环中余下的代码,将这个数打印出来.
(2)如果程序陷入无限循环,可按Ctrl + C,也可关闭显示程序输出的终端窗口。
7.3 使用while
循环处理列表和字典
for
循环是一种遍历列表的有效方式,但不应在for
循环中修改列表,否则将导致Python难以跟踪其中的元素。要在遍历列表的同时对其进行修改,可使用while
循环。通过将while
循环同列表和字典结合起来使用,可收集、存储并组织大量输入,供以后查看和显示。
(1)删除为特定值的所有列表元素
pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
print(pets)while 'cat' in pets:pets.remove('cat')print(pets)
首先创建一个列表,其中包含多个值为'cat'
的元素。打印这个列表后,Python进入while
循环,因为它发现'cat'
在列表中至少出现了一次。进入该循环后,Python删除第一个'cat'
并返回到while
代码行,然后发现'cat'
还包含在列表中,因此再次进入循环。它不断删除'cat'
,直到这个值不再包含在列表中,然后退出循环并再次打印列表.
(2)使用用户输入来填充字典
responses = {}# 设置一个标志,指出调查是否继续。polling_active = Truewhile polling_active:# 提示输入被调查者的名字和回答。
❶ name = input("\nWhat is your name? ")response = input("Which mountain would you like to climb someday? ")# 将回答存储在字典中。
❷ responses[name] = response# 看看是否还有人要参与调查。
❸ repeat = input("Would you like to let another person respond? (yes/ no) ")if repeat == 'no':polling_active = False# 调查结束,显示结果。print("\n--- Poll Results ---")
❹ for name, response in responses.items():print(f"{name} would like to climb {response}.")
在本章中,学习了:如何在程序中使用
input()
来让用户提供信息;如何处理文本和数的输入,以及如何使用while
循环让程序按用户的要求不断运行;多种控制while
循环流程的方式:设置活动标志、使用break
语句以及使用continue
语句;如何使用while
循环在列表之间移动元素,以及如何从列表中删除所有包含特定值的元素;如何结合使用while
循环和字典。
第 8 章 函数
函数是带名字的代码块,用于完成具体的工作。要执行函数定义的特定任务,可调用 该函数。需要在程序中多次执行同一项任务时,无须反复编写完成该任务的代码,只需要调用执行该任务的函数,让Python运行其中的代码即可。
8.1 定义函数
❶ def greet_user():
❷ """显示简单的问候语。"""
❸ print("Hello!")❹ greet_user()
本例演示了最简单的函数结构。❶处的代码行使用关键字def
来告诉Python,你要定义一个函数。这是函数定义 ,向Python指出了函数名,还可能在圆括号内指出函数为完成任务需要什么样的信息。在这里,函数名为greet_user()
,它不需要任何信息就能完成工作,因此括号是空的(即便如此,括号也必不可少)。最后,定义以冒号结尾。
紧跟在def greet_user():
后面的所有缩进行构成了函数体。❷处的文本是称为文档字符串 (docstring)的注释,描述了函数是做什么的。文档字符串用三引号括起,Python使用它们来生成有关程序中函数的文档。
代码行print("Hello!")
(见❸)是函数体内的唯一一行代码,因此greet_user()
只做一项工作:打印Hello!
。
要使用这个函数,可调用它。函数调用 让Python执行函数的代码。要调用 函数,可依次指定函数名以及用圆括号括起的必要信息,如❹处所示。由于这个函数不需要任何信息,调用它时只需输入greet_user()
即可。和预期一样,它打印Hello!
(1)向函数传递信息
在函数定义def greet_user()
的括号内添加username
。通过在这里添加username
,可让函数接受你给username
指定的任何值。现在,这个函数要求你调用它时给username
指定一个值。调用greet_user()
时,可将一个名字传递给它,如下所示.
def greet_user(username):"""显示简单的问候语。"""print(f"Hello, {username.title()}!")greet_user('jesse')
(2)实参和形参
前面定义函数greet_user()
时,要求给变量username
指定一个值。调用这个函数并提供这种信息(人名)时,它将打印相应的问候语。
在函数greet_user()
的定义中,变量username
是一个形参 (parameter),即函数完成工作所需的信息。在代码greet_user('jesse')
中,值'jesse'
是一个实参 (argument),即调用函数时传递给函数的信息。调用函数时,将要让函数使用的信息放在圆括号内。在greet_user('jesse')
中,将实参'jesse'
传递给了函数greet_user()
,这个值被赋给了形参username
。
注意 大家有时候会形参、实参不分,因此如果你看到有人将函数定义中的变量称为实参或将函数调用中的变量称为形参,不要大惊小怪。
8.2 传递实参
函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参。向函数传递实参的方式很多:可使用位置实参 ,这要求实参的顺序与形参的顺序相同;也可使用关键字实参 ,其中每个实参都由变量名和值组成;还可使用列表和字典。
(1)位置实参
调用函数时,Python必须将函数调用中的每个实参都关联到函数定义中的一个形参。为此,最简单的关联方式是基于实参的顺序。这种关联方式称为位置实参 。
❶ def describe_pet(animal_type, pet_name):"""显示宠物的信息。"""print(f"\nI have a {animal_type}.")print(f"My {animal_type}'s name is {pet_name.title()}.")❷ describe_pet('hamster', 'harry')
(2)关键字实参
关键字实参 是传递给函数的名称值对。因为直接在实参中将名称和值关联起来,所以向函数传递实参时不会混淆(不会得到名为Hamster的harry这样的结果)。关键字实参让你无须考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。
def describe_pet(animal_type, pet_name):"""显示宠物的信息。"""print(f"\nI have a {animal_type}.")print(f"My {animal_type}'s name is {pet_name.title()}.")describe_pet(animal_type='hamster', pet_name='harry')
(3)默认值
编写函数时,可给每个形参指定默认值 。在调用函数中给形参提供了实参时,Python将使用指定的实参值;否则,将使用形参的默认值。因此,给形参指定默认值后,可在函数调用中省略相应的实参。使用默认值可简化函数调用,还可清楚地指出函数的典型用法。
def describe_pet(pet_name, animal_type='dog'):"""显示宠物的信息。"""print(f"\nI have a {animal_type}.")print(f"My {animal_type}'s name is {pet_name.title()}.")describe_pet(pet_name='willie')
(4)避免实参错误
等你开始使用函数后,如果遇到实参不匹配错误,不要大惊小怪。你提供的实参多于或少于函数完成工作所需的信息时,将出现实参不匹配错误。
没有指定任何实参,会出现错误
def describe_pet(animal_type, pet_name):"""显示宠物的信息。"""print(f"\nI have a {animal_type}.")print(f"My {animal_type}'s name is {pet_name.title()}.")describe_pet()
8.3 返回值
函数并非总是直接显示输出,它还可以处理一些数据,并返回一个或一组值。函数返回的值称为返回值 。在函数中,可使用return
语句将值返回到调用函数的代码行。返回值让你能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序。
(1)返回简单值
❶ def get_formatted_name(first_name, last_name):"""返回整洁的姓名。"""
❷ full_name = f"{first_name} {last_name}"
❸ return full_name.title()❹ musician = get_formatted_name('jimi', 'hendrix')print(musician)
(2)返回字典
函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。
8.4 传递列表
(1)禁止函数修改列表
要将列表的副本传递给函数,可以像下面这样做:
function_name(list_name_[:])
切片表示法[:]
创建列表的副本。
这样函数print_models()
依然能够完成工作,因为它获得了所有未打印的设计的名称,但使用的是列表unprinted_designs
的副本,而不是列表unprinted_designs
本身。像以前一样,列表completed_models
也将包含打印好的模型的名称,但函数所做的修改不会影响到列表unprinted_designs
。
8.5 传递任意数量的实参
有时候,预先不知道函数需要接受多少个实参,好在Python允许函数从调用语句中收集任意数量的实参。
def make_pizza(*toppings):"""打印顾客点的所有配料。"""print(toppings)make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')('pepperoni',)
('mushrooms', 'green peppers', 'extra cheese')
形参名*toppings
中的星号让Python创建一个名为toppings
的空元组,并将收到的所有值都封装到这个元组中。函数体内的函数调用print()
通过生成输出,证明Python能够处理使用一个值来调用函数的情形,也能处理使用三个值来调用函数的情形。它以类似的方式处理不同的调用。注意,Python将实参封装到一个元组中,即便函数只收到一个值.
(1)使用任意数量的关键字实参
def build_profile(first, last, **user_info):"""创建一个字典,其中包含我们知道的有关用户的一切。"""
❶ user_info['first_name'] = firstuser_info['last_name'] = lastreturn user_infouser_profile = build_profile('albert', 'einstein',location='princeton',field='physics')print(user_profile){'location': 'princeton', 'field': 'physics',
'first_name': 'albert', 'last_name': 'einstein'}
形参**user_info
中的两个星号让Python创建一个名为user_info
的空字典,并将收到的所有名称值对都放到这个字典中。在这个函数中,可以像访问其他字典那样访问user_info
中的名称值对。
注意 你经常会看到形参名
**kwargs
,它用于收集任意数量的关键字实参。
8.6 将函数存储在模块中
使用函数的优点之一是可将代码块与主程序分离。通过给函数指定描述性名称,可让主程序容易理解得多。你还可以更进一步,将函数存储在称为模块 的独立文件中,再将模块导入 到主程序中。import
语句允许在当前运行的程序文件中使用模块中的代码。
通过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上。这还能让你在众多不同的程序中重用函数。将函数存储在独立文件中后,可与其他程序员共享这些文件而不是整个程序。知道如何导入函数还能让你使用其他程序员编写的函数库。
(1)导入整个模块
要让函数是可导入的,得先创建模块。模块 是扩展名为.py的文件,包含要导入到程序中的代码。
导入方法:只需编写一条import
语句并在其中指定模块名,就可在程序中使用该模块中的所有函数。举个例子:
pizza.py内容:
def make_pizza(size, *toppings):"""概述要制作的比萨。"""print(f"\nMaking a {size}-inch pizza with the following toppings:")for topping in toppings:print(f"- {topping}")making_pizzas.py内容import pizza❶ pizza.make_pizza(16, 'pepperoni')pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
(2)导入特定的函数
还可以导入模块中的特定函数,这种导入方法的语法如下:
from module_name import function_name
通过用逗号分隔函数名,可根据需要从模块中导入任意数量的函数:
from module_name import function_0, function_1, function_2
(3)使用as
给函数指定别名
如果要导入函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的别名 :函数的另一个名称,类似于外号。要给函数取这种特殊外号,需要在导入它时指定。
下面给函数make_pizza()
指定了别名mp()
。这是在import
语句中使用make_pizza as mp
实现的,关键字as
将函数重命名为指定的别名:
from pizza import make_pizza as mpmp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')
(4)使用as
给模块指定别名
还可以给模块指定别名。通过给模块指定简短的别名(如给模块pizza
指定别名p
),让你能够更轻松地调用模块中的函数。相比于pizza.make_pizza()
,p.make_pizza()
更为简洁:
import pizza as pp.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
上述import
语句给模块pizza
指定了别名p
,但该模块中所有函数的名称都没变。要调用函数make_pizza()
,可编写代码p.make_pizza()
而非pizza.make_pizza()
。这样不仅代码更简洁,还让你不用再关注模块名,只专注于描述性的函数名。这些函数名明确指出了函数的功能,对于理解代码而言,比模块名更重要。
(5)导入模块中的所有函数
使用星号(*
)运算符可让Python导入模块中的所有函数:
from pizza import *make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
import
语句中的星号让Python将模块pizza
中的每个函数都复制到这个程序文件中。由于导入了每个函数,可通过名称来调用每个函数,而无须使用句点表示法。然而,使用并非自己编写的大型模块时,最好不要采用这种导入方法。这是因为如果模块中有函数的名称与当前项目中使用的名称相同,可能导致意想不到的结果:Python可能遇到多个名称相同的函数或变量,进而覆盖函数,而不是分别导入所有的函数。