python学习8(函数)
一、让实参变成可选的
并非所有的人都有中间名,但如果你调用这个函数时只提供了名和姓,它将不能正确
地运行。为让中间名变成可选的,可给实参middle_name指定一个默认值——空字符串,并在用
户没有提供中间名时不使用这个实参。为让get_formatted_name()在没有提供中间名时依然可行,
可给实参middle_name指定一个默认值——空字符串,并将其移到形参列表的末尾:
def get_formatted_name(first_name, last_name, middle_name=''): """返回整洁的姓名"""if middle_name: full_name = first_name + ' ' + middle_name + ' ' + last_name else: full_name = first_name + ' ' + last_name return full_name.title() musician = get_formatted_name('jimi', 'hendrix') print(musician)
musician = get_formatted_name('john', 'hooker', 'lee') print(musician)
说明:if middle_name将为True。如果提供了中间名,就将名、中间名和
姓合并为姓名,然后将其修改为首字母大写格式,并返回到函数调用行。在函数调用行,将返回
的值存储在变量musician中;然后将这个变量的值打印出来。
二、返回字典
def build_person(first_name, last_name): """返回一个字典,其中包含有关一个人的信息""" person = {'first': first_name, 'last': last_name} return person musician = build_person('jimi', 'hendrix') print(musician) {'first': 'jimi', 'last': 'hendrix'}
可以轻松地
扩展这个函数,使其接受可选值,如中间名、年龄、职业或你要存储的其他任何信息
def build_person(first_name, last_name, age=''): """返回一个字典,其中包含有关一个人的信息""" person = {'first': first_name, 'last': last_name} if age: person['age'] = age return person musician = build_person('jimi', 'hendrix', age=27) print(musician)
三、结合使用函数和while 循环
但这个while循环存在一个问题:没有定义退出条件。请用户提供一系列输入时,该在什么
地方提供退出条件呢?我们要让用户能够尽可能容易地退出,因此每次提示用户输入时,都应提
供退出途径。每次提示用户输入时,都使用break语句提供了退出循环的简单途径:
def get_formatted_name(first_name, last_name): """返回整洁的姓名""" full_name = first_name + ' ' + last_name return full_name.title() while True: print("\nPlease tell me your name:") print("(enter 'q' at any time to quit)") f_name = input("First name: ") if f_name == 'q': break l_name = input("Last name: ") if l_name == 'q': break formatted_name = get_formatted_name(f_name, l_name) print("\nHello, " + formatted_name + "!")
我们添加了一条消息来告诉用户如何退出,然后在每次提示用户输入时,都检查他输入的是
否是退出值,如果是,就退出循环。现在,这个程序将不断地问候,直到用户输入的姓或名为'q'
为止:
Please tell me your name: (enter 'q' at any time to quit) First name: eric Last name: matthes Hello, Eric Matthes! Please tell me your name: (enter 'q' at any time to quit) First name: q
四、传递列表
假设有一个用户列表,我们要问候其中的每位用户。下面的示例将一个名字列表传递给一个
名为greet_users()的函数,这个函数问候列表中的每个人:
def greet_users(names): """向列表中的每位用户都发出简单的问候""" for name in names: msg = "Hello, " + name.title() + "!" print(msg) usernames = ['hannah', 'ty', 'margot'] greet_users(usernames) Hello, Hannah! Hello, Ty! Hello, Margot!
4.1、在函数中修改列表
将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永
久性的,这让你能够高效地处理大量的数据。
来看一家为用户提交的设计制作3D打印模型的公司。需要打印的设计存储在一个列表中,
打印后移到另一个列表中。下面是在不使用函数的情况下模拟这个过程的代码:
# 首先创建一个列表,其中包含一些要打印的设计 unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron'] completed_models = [] # 模拟打印每个设计,直到没有未打印的设计为止 # 打印每个设计后,都将其移到列表completed_models中 while unprinted_designs: current_design = unprinted_designs.pop() #模拟根据设计制作3D打印模型的过程 print("Printing model: " + current_design) completed_models.append(current_design) # 显示打印好的所有模型 print("\nThe following models have been printed:") for completed_model in completed_models: print(completed_model)
Printing model: dodecahedron
Printing model: robot pendant
Printing model: iphone case
The following models have been printed:
dodecahedron
robot pendant
iphone case
升级:
为重新组织这些代码,我们可编写两个函数,每个都做一件具体的工作。大部分代码都与
原来相同,只是效率更高。第一个函数将负责处理打印设计的工作,而第二个将概述打印了哪
些设计:
def print_models(unprinted_designs, completed_models): """ 模拟打印每个设计,直到没有未打印的设计为止 打印每个设计后,都将其移到列表completed_models中 """ while unprinted_designs: current_design = unprinted_designs.pop() # 模拟根据设计制作3D打印模型的过程 print("Printing model: " + current_design) completed_models.append(current_design) def show_completed_models(completed_models): """显示打印好的所有模型""" print("\nThe following models have been printed:") for completed_model in completed_models: print(completed_model) unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron'] completed_models = [] print_models(unprinted_designs, completed_models) show_completed_models(completed_models)
在Ø处,我们定义了函数print_models(),它包含两个形参:一个需要打印的设计列表和一
个打印好的模型列表。给定这两个列表,这个函数模拟打印每个设计的过程:将设计逐个地从未
打印的设计列表中取出, 并加入到打印好的模型列表中。在 处, 我们定义了函数
show_completed_models() ,它包含一个形参:打印好的模型列表。给定这个列表,函数
show_completed_models()显示打印出来的每个模型的名称。
这个程序的输出与未使用函数的版本相同,但组织更为有序。完成大部分工作的代码都移到
了两个函数中,让主程序更容易理解。只要看看主程序,你就知道这个程序的功能容易看清得多:
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron'] completed_models = [] print_models(unprinted_designs, completed_models) show_completed_models(completed_models)
4.2、禁止函数修改列表
有时候,需要禁止函数修改列表。例如,假设像前一个示例那样,你有一个未打印的设计列
表,并编写了一个将这些设计移到打印好的模型列表中的函数。你可能会做出这样的决定:即便
打印所有设计后,也要保留原来的未打印的设计列表,以供备案。但由于你将所有的设计都移出
了unprinted_designs,这个列表变成了空的,原来的列表没有了。为解决这个问题,可向函数传
递列表的副本而不是原件;这样函数所做的任何修改都只影响副本,而丝毫不影响原件。
要将列表的副本传递给函数,可以像下面这样做:
function_name(list_name[:])
切片表示法[:]创建列表的副本。在print_models.py中,如果不想清空未打印的设计列表,
可像下面这样调用print_models():
print_models(unprinted_designs[:], completed_models)
这样函数print_models()依然能够完成其工作,因为它获得了所有未打印的设计的名称,但
它使用的是列表unprinted_designs的副本,而不是列表unprinted_designs本身。像以前一样,列
表completed_models也将包含打印好的模型的名称,但函数所做的修改不会影响到列表
unprinted_designs。
4.3、传递任意数量的实参
例如,来看一个制作比萨的函数,它需要接受很多配料,但你无法预先确定顾客要多少种配
料。下面的函数只有一个形参*toppings,但不管调用语句提供了多少实参,这个形参都将它们
统统收入囊中:
def make_pizza(*toppings): """打印顾客点的所有配料""" print(toppings) make_pizza('pepperoni') make_pizza('mushrooms', 'green peppers', 'extra cheese')
现在,我们可以将这条print语句替换为一个循环,对配料列表进行遍历,并对顾客点的比
萨进行描述:
def make_pizza(*toppings): """概述要制作的比萨""" print("\nMaking a pizza with the following toppings:") for topping in toppings: print("- " + topping) make_pizza('pepperoni') make_pizza('mushrooms', 'green peppers', 'extra cheese') Making a pizza with the following toppings: - pepperoni Making a pizza with the following toppings: - mushrooms - green peppers - extra cheese
4.4、结合使用位置实参和任意数量实参
例如,如果前面的函数还需要一个表示比萨尺寸的实参,必须将该形参放在形参*toppings
的前面:
def make_pizza(size, *toppings): """概述要制作的比萨""" print("\nMaking a " + str(size) + "-inch pizza with the following toppings:") for topping in toppings: print("- " + topping) make_pizza(16, 'pepperoni') make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese') Making a 16-inch pizza with the following toppings: - pepperoni Making a 12-inch pizza with the following toppings: - mushrooms - green peppers - extra cheese
4.5、使用任意数量的关键字实参
def build_profile(first, last, **user_info): """创建一个字典,其中包含我们知道的有关用户的一切""" profile = {} profile['first_name'] = first profile['last_name'] = last for key, value in user_info.items(): profile[key] = value return profile user_profile = build_profile('albert', 'einstein', location='princeton', field='physics') print(user_profile)
函数build_profile()的定义要求提供名和姓,同时允许用户根据需要提供任意数量的名称—
值对。形参**user_info中的两个星号让Python创建一个名为user_info的空字典,并将收到的所
有名称—值对都封装到这个字典中。在这个函数中,可以像访问其他字典那样访问user_info中的
名称—值对。
在build_profile()的函数体内,我们创建了一个名为profile的空字典,用于存储用户简介。
在Ø处,我们将名和姓加入到这个字典中,因为我们总是会从用户那里收到这两项信息。在处,
我们遍历字典user_info中的键—值对,并将每个键—值对都加入到字典profile中。最后,我们将
字典profile返回给函数调用行。
我们调用build_profile(),向它传递名('albert')、姓('einstein')和两个键—值对
(location='princeton'和field='physics'),并将返回的profile存储在变量user_profile中,再
打印这个变量:
{'first_name': 'albert', 'last_name': 'einstein',
'location': 'princeton', 'field': 'physics'}
在这里,返回的字典包含用户的名和姓,还有求学的地方和所学专业。调用这个函数时,不
管额外提供了多少个键—值对,它都能正确地处理。

浙公网安备 33010602011771号