5. 函数
5.1 定义函数
1、函数定义
函数是带名字的代码块,用于完成具体工作,当需要在程序中多次执行同一项任务时,即可调用函数,程序的编写、阅读、测试和修复都将更容易。
- def 关键字用于定义函数
- def 关键字后跟函数名( def 函数名( ) )
- 函数名后括号内有形参,其存储着传入函数内部的参数
- 紧跟在 def 函数名() 后的所有缩进构成函数体
- 用三引号括起来的是文档字符串,用于生成有关程序中函数的文档
def greet_user():
"""显示简单的问候语"""
print('Hello!')
greet_user()
输出:
Hello!
进程已结束,退出代码 0
2、向函数传递信息
def greet_user(username):
"""显示简单的问候语"""
print('Hello %s!' % username)
greet_user('liming')
输出:
Hello liming!
进程已结束,退出代码 0
3、实参和形参
- 实参:调用函数时传递给函数的信息,在调用函数时输入,在函数体外部。
- 形参:函数完成其工作所需的一项信息,在定义函数时的函数名后括号内输入,在函数体内部。
如在上述 5.2 中 greet_user(username) 定义中的 username 为形参,greet_user(‘liming’) 中的 liming 为实参。
5.2 传递实参
函数的定义和调用可能分别包含多个形参和实参,向函数中传递实参可使用位置实参、关键字实参、列表、字典等。
1、位置实参
位置实参的含义是基于函数调用中实参的顺序来关联函数定义中的形参。
def greet_user(username, usersex):
"""显示简单的问候语"""
print('Hello ' + username + ',you are a handsome ' + usersex + '!')
greet_user('liming', 'boy')
输出:
Hello liming,you are a handsome boy!
进程已结束,退出代码 0
位置实参的顺序很重要,顺序出错会导致输出结果错误。
2、关键字实参
关键字实参是传递给函数的名称-值对,在调用函数时直接将名称和值关联起来,这样向函数传递实参时就不会混淆,无需考虑实参顺序。
def greet_user(username, usersex):
"""显示简单的问候语"""
print('Hello ' + username + ',you are a handsome ' + usersex + '!')
greet_user(username='liming', usersex='boy')
输出:
Hello liming,you are a handsome boy!
进程已结束,退出代码 0
3、默认值
编写代码时,可给每个形参指定默认值。调用函数时,如果没有给对应形参提供实参,则形参使用默认值,否则形参使用实参提供的值而不管默认值,即实参提供的值优先级高于形参默认值。
def greet_user(username, usersex='girl'):
"""显示简单的问候语"""
print('Hello ' + username + ',you are a handsome ' + usersex + '!')
greet_user(username='liming', usersex='boy')
输出:
Hello liming,you are a handsome boy!
进程已结束,退出代码 0
5.3 返回值
1、返回简单值
函数并非总是显示输出,相反它也可以处理一些数据,并返回一个或一组值,即返回值。可使用 return 语句将值返回到调用函数的代码行。
def greet_user(first_name, last_name='girl'):
"""返回全名"""
full_name = first_name + ' ' + last_name
return full_name
name = greet_user('li', 'ming')
print(name)
输出:
li ming
进程已结束,退出代码 0
2、让实参变得可选
有时候需要让实参变得可选,这样使用函数的人就只需要在必要时才提供额外信息,可使用默认值让实参变得可选,而定义这个默认值时要将其放在形参的最后一个。
def greet_user(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
name1 = greet_user('li', 'ming', 'hong')
name2 = greet_user('li', 'ming')
print(name1)
print(name2)
输出:
li hong ming
li ming
进程已结束,退出代码 0
3、返回字典
函数可返回任何类型的值,包括列表、字典等较为复杂的数据结构。
def greet_user(first_name, last_name):
"""返回一个字典,其中包含一个人的信息"""
person = {'first': first_name, 'last': last_name}
return person
name = greet_user('li', 'ming')
print(name)
输出:
{'first': 'li', 'last': 'ming'}
进程已结束,退出代码 0
对上述函数进行扩展,增加字典中的内容。
def greet_user(first_name, last_name, age=''):
"""返回一个字典,其中包含一个人的信息"""
person = {'first': first_name, 'last': last_name}
if age:
person['age'] = age
return person
name = greet_user('li', 'ming', age=18)
print(name)
输出:
{'first': 'li', 'last': 'ming', 'age': 18}
进程已结束,退出代码 0
4、结合使用函数和 while 循环
可将函数和任何 python 结构结合起来使用。
def get_name(first_name, last_name):
"""返回完整的名字"""
full_name = first_name + ' ' + last_name
return full_name.title()
while True:
print('\n请输入姓名(输入“结束”可退出)')
f_name = input('请输入姓:\n')
if f_name == '结束':
break
l_name = input('请输入名:\n')
if f_name == '结束':
break
full_name = get_name(f_name, l_name)
print('\n你好,' + full_name + '!')
输出:
请输入姓名(输入“结束”可退出)
请输入姓:
李
请输入名:
明
你好,李 明!
请输入姓名(输入“结束”可退出)
请输入姓:
结束
进程已结束,退出代码 0
5.4 传递列表
向函数传递列表很有用,这种列表包含的可能是名字、数字或更复杂的对象(如字典),列表传递给函数后,函数就可以直接访问其内容。
1、在函数中修改列表
在函数中对列表进行任何修改都是永久性的,这能让你高效处理大量数据。
def print_models(unprinted_design, completed_model):
"""
模拟打印每个设计,直到没有未打印的设计为止
打印每个设计后,都将其移动到列表 completed_models 中
"""
while unprinted_design:
current_design = unprinted_design.pop()
# 模拟根据设计制作3D打印模型过程
print('Printing model:' + current_design)
completed_model.append(current_design)
return completed_model
def show_completed_models(completed_model):
"""显示所有打印好的模型"""
print('\nThe following models have been printed:')
for comp_model in completed_model:
print(comp_model)
# 首先创建一个列表,其中包含一些要打印的设计
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
completed_models = []
print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)
输出:
Printing model:dodecahedron
Printing model:robot pendant
Printing model:iphone case
The following models have been printed:
dodecahedron
robot pendant
iphone case
进程已结束,退出代码 0
2、禁止函数修改列表
有时候需要禁止函数修改列表,对此可向函数传递列表副本而不是原件,这样函数所做的任何修改都只会影响副本,而不影响原件。
function_name(list_name[ : ])
在1中如果不想清空未打印的设计列表,可像下面这样调用 print_models()。
print_models(unprinted_designs[:], completed_models)
5.5 传递任意数量的实参
有时候预先不知道函数需要接受多少个实参,好在 python 允许函数从调用语句中收集任意数量的实参。
1、结合使用位置实参和任意数量实参
如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后,python 先匹配位置实参和关键字实参,再将剩下的实参都收集到最后一个形参中。
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
进程已结束,退出代码 0
Python 将收到的多余实参以元组的数据格式存储在形参中,上述形参名 *toppings 中的星号让 python 创建一个名为 toppings 的空元组,并将收到的所有值都封装到这个元组中。
2、使用任意数量的关键字实参
有时候函数需要接收任意数量实参,但预先不知道传递给函数的会是什么信息,这时可将函数编写成能接收任意数量的键-值对。
def build_profile(first, last, **user_info):
"""创建一个字典,其中包含用户一切信息"""
profile = {'first_name': first, 'last_name': last}
for key,value in user_info.items():
profile[key] = value
return profile
user_profile = build_profile('albert', 'einstein',
location='princeton',
filed='physics')
print(user_profile)
输出:
{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'filed': 'physics'}
进程已结束,退出代码 0
其中形参 **user_info 中的两个星号让 python 创建一个名为 user_info 的字典,并将收到的所有名称-值对都封装到这个字典中。