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'}

  在这里,返回的字典包含用户的名和姓,还有求学的地方和所学专业。调用这个函数时,不
管额外提供了多少个键—值对,它都能正确地处理。

posted @ 2017-12-15 10:49  是你的鱼尾纹  阅读(460)  评论(0)    收藏  举报