8.1 定义函数
一个简单的函数
def greet_user():
'''显示简单的问候语'''
print('Hello!')
greet_user()
'''
输出:
Hello!
'''
8.1.1 向函数传递信息
def greet_user(username):
# 显示简单的问候语
print(f'Hello, {username.title()}.')
greet_user('jesse')
greet_user('jim')
'''
输出:
Hello, Jesse.
Hello, Jim.
'''
8.1.2 形参和实参
上述代码中,变量username 就是形参,值 ‘jesse’ 和 ‘jim’ 就是实参
8.2 传递参数
函数定义中可能包括多个形参,函数调用时也可能包括多个实参,向函数传递实参的方法有:位置实参、关键字实参
8.2.1 位置实参
调用函数时,根据参数位置将实参关联到形参
def describe_pet(animal_type, pet_name):
'''显示宠物信息'''
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name}.")
describe_pet('mouse', 'Micky')
describe_pet('dog', 'Harry')
describe_pet('Harry', 'dog')
'''
I have a mouse.
My mouse's name is Micky.
I have a dog.
My dog's name is Harry.
I have a Harry.
My Harry's name is dog.
'''
- 多次调用函数
- 位置实参的顺序很重要,第二次和第三次调用就说明了这个问题
8.2.2 关键字实参
关键字实参直接在实参中将名称和值关联起来,这样可以不考虑实参顺序
def describe_pet(animal_type, pet_name):
'''显示宠物信息'''
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name}.")
describe_pet(animal_type = 'mouse',pet_name = 'Micky')
describe_pet(pet_name = 'Micky', animal_type = 'mouse')
'''
输出:
I have a mouse.
My mouse's name is Micky.
I have a mouse.
My mouse's name is Micky.
进程已结束,退出代码为 0
'''
8.2.3 默认值
编写函数时,可以给形参指定默认值,在调用函数时,给形参提供了实参时,程序将使用提供的实参,否则将使用形参的默认值
这里需要注意,一定要考虑参数位置(这里,形参-默认值也占据一个形参位置)
def describe_pet(pet_name, animal_type = 'mouse'):
'''显示宠物信息'''
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name}.")
describe_pet('Micky')
describe_pet(pet_name = 'Harry', animal_type = 'dog')
'''
输出:
I have a mouse.
My mouse's name is Micky.
I have a dog.
My dog's name is Harry.
'''
8.2.4 等效的函数调用
可以混合使用位置参数、关键字参数和默认值
8.2.5 避免实参错误
略
8.3 返回值
函数可以使用 return 语句返回一个或者一组值
8.3.1 返回简单值
def get_formatted_name(first_name, last_name):
'''返回整洁的姓名'''
full_name = f"{first_name} {last_name}"
return full_name.title()
musician = get_formatted_name('jim', 'hendrix')
print(musician)
'''
输出:
Jim Hendrix
'''
8.3.2 让实参变成可选的
并非所有人都有中间名,如果要让中间名变成可选的,可以将中间名移到参数最后,采用默认值的方法
def get_formatted_name(first_name, last_name, middle_name = ''):
'''返回整洁的姓名'''
if middle_name:
full_name = f"{first_name} {middle_name} {last_name}"
else:
full_name = f"{first_name} {last_name}"
return full_name.title()
musician = get_formatted_name('jim', 'hendrix')
print(musician)
musician = get_formatted_name('john', 'hooker', 'lee')
print(musician)
'''
输出:
Jim Hendrix
John Lee Hooker
'''
8.3.3 返回字典
def build_person(first_name, last_name):
person = {'first': first_name, 'last': last_name}
return person
musician = build_person('jim', 'hendrix')
print(musician)
'''
输出:
{'first': 'jim', 'last': 'hendrix'}
'''
8.3.4 结合使用函数和 while 循环
def get_formatted_name(first_name, last_name):
'''返回整洁的姓名'''
full_name = f"{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(f"\nHello, {formatted_name}!")
'''
输出:
Please tell me your name:
(enter 'q' at any time to quit)
First name: zhang
Last name: xy
Hello, Zhang Xy!
Please tell me your name:
(enter 'q' at any time to quit)
First name: wang
Last name: q
'''
8.4 传递列表
向函数传递一个列表
def greet_users(names):
for name in names:
msg = f"Hello, {name.title()}."
print(msg)
usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)
'''
输出:
Hello, Hannah.
Hello, Ty.
Hello, Margot.
'''
8.4.1 在函数中修改列表
将列表传递给函数后,可以对其进行修改,函数对列表的修改是永久性的
将未打印列表中的元素打印,打印完成的元素移到完成打印的列表中
常规程序:
unprint_designs = ['phone case', 'robot pendant', 'dodecahedron']
completed_designs = []
while unprint_designs:
current_design = unprint_designs.pop()
print(f"Printing model: {current_design}")
completed_designs.append(current_design)
print("\nThe following models have been printed: ")
for completed_design in completed_designs:
print(completed_design)
'''
输出:
Printing model: dodecahedron
Printing model: robot pendant
Printing model: phone case
The following models have been printed:
dodecahedron
robot pendant
phone case
'''
优化代码(每一个函数尽量只做一件事情,这样效果更高,主函数也更加简洁;第一个函数负责打印和移动列表元素,第二个函数负责展示已打印的信息)
def print_modules(unprinted_designs, completed_designs):
while unprinted_designs:
current_design = unprint_designs.pop()
print(f"Printing model: {current_design}")
completed_designs.append(current_design)
def show_completed_designs(completed_designs):
print("\nThe following models have been printed: ")
for completed_design in completed_designs:
print(completed_design)
unprint_designs = ['phone case', 'robot pendant', 'dodecahedron']
completed_designs = []
print_modules(unprint_designs, completed_designs)
show_completed_designs(completed_designs)
'''
输出:
Printing model: dodecahedron
Printing model: robot pendant
Printing model: phone case
The following models have been printed:
dodecahedron
robot pendant
phone case
'''
8.4.2 禁止函数修改列表
其实不是严格意义上的禁止修改列表,而是将原列表上产生一个备份,在备份列表进行操作,这样就不影响原列表
function_name(list_name[:])
8.5 传递任意数量的参数
*toppings 中的星号让程序创建一个名为 toppings 的空元组,并将收到的所有值装入到这个元组中
def make_pizza(*toppings):
print("\nMaking a pizza with the following toppings: ")
for topping in toppings:
print(f"- {topping}")
make_pizza('peperoni')
make_pizza('mushrooms', 'green peppers', 'extra chesese')
'''
输出:
Making a pizza with the following toppings:
- peperoni
Making a pizza with the following toppings:
- mushrooms
- green peppers
- extra chesese
'''
8.5.1 结合使用位置的实参和任意数量的实参
如果函数要接受不同类型的实参,必须将接纳任意数量实参的形参放在最后,这样,程序将先匹配位置参数,再将剩余的实参都收集到最后一个形参中,如果有默认关键字参数,可以放到最后
def make_pizza(size, *toppings):
print(f"\nMaking a {size}-inch pizza with the following toppings: ")
for topping in toppings:
print(f"- {topping}")
make_pizza(16, 'peperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra chesese')
'''
输出:
Making a 16-inch pizza with the following toppings:
- peperoni
Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra chesese
'''
8.5.2 使用任意数量的关键字实参
**user_info 用于收集任意数量的键值对
def build_profile(first, last, **user_info):
user_info['first_name'] = first
user_info['last_name'] = last
return user_info
# 关键字实参直接以键值对的形式存储,非关键字实参改为键值对形式追加存储
user_proflie = build_profile('albert', 'einstein', location = 'princeton', field = 'physics')
print(user_proflie)
'''
输出:
{'location': 'princeton', 'field': 'physics', 'first_name': 'albert', 'last_name': 'einstein'}
'''
8.6 将函数存储在模块中
用 import 语句让当前程序使用模块中的代码,模块可以理解为独立文件,该文件中有很多好用的函数
8.6.1 导入整个模块
将 pizza.py 文件作为模块,在making_pizza.py 中调用该模块,使用模块中的函数使用的语法是:
module_name.function_name()
pizza.py 文件
def make_pizza(size, *toppings):
# pizza.py 模块,包含函数 make_pizza()
print(f"\nMaking a {size}-inch pizza with the following toppings: ")
for topping in toppings:
print(f"- {topping}")
making_pizza.py 文件
import pizza
pizza.make_pizza(16, 'pepperoni')
pizza.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
'''
8.6.2 导入特定的函数
导入模块中特定的函数,语法如下:
from module_name import function_name
如果导入多个函数,用逗号分隔
from module_name import function0, function1, function2
在这种情况下,调用函数时,无需使用 . 运算符
from pizza import make_pizza
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
'''
8.6.3 使用 as 给函数指定别名
如果要导入的函数与程序中现有的名称冲突,或者函数的名称太长,就可以给函数取别名
语法如下:
from module_name import function_name as mp
上小节代码可以表示为
from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')
8.6.4 使用 as 给模块指定别名
还可以给模块指定别名,语法如下:
import module_name as mn
8.6.1 代码可以改写为:
import pizza as mn
mn.make_pizza(16, 'pepperoni')
mn.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
8.6.5 导入模块中的所有函数
语法如下:
from module_name import *
这种做法不推荐使用,建议使用
- 只导入需要使用的函数,不需要 . 运算符
- 导入整个模块,使用 . 运算符调用函数
8.7 函数编写指南
- 函数命名只用小写字母和下划线
- 函数的注释应紧跟在函数定义后面,并采用文档字符串格式
- 给形参指定默认值时,等号两边不要有空格
8.8 小结
略