第八章 函数
8.1 定义函数
要定义一个函数时,要使用关键字def来告诉Python你要定义一个函数。
定义函数的基本格式为:
例如:
❶ def greet_user():
❷ """显示简单的问候语"""
❸ print("Hello!")
❹ greet_user()
❶处的代码使用关键字def来告诉Python你要定义一个函数。这是函数定义,向Python指出了函数名,还可能在括号内指出函数为完成其任务需要什么样的信息,最后,定义以冒号结尾。
而后面所有的缩进就构成了函数体。
❷处的文本被称为文档字符串的注释,描述了函数是做什么的。文档字符串用三引号括起,Python使用它们来生成有关程序中函数的文档。
要调用函数,可依次指定函数名以及用括号括起的必要信息
8.1.1 向函数传递信息
若要向函数传递信息,可在函数名的括号内定义形参,以便来向函数传递信息。
例如:
❶ def greet_user(username):
❷ """显示简单的问候语"""
❸ print("Hello!"+ usename)
❹ greet_user("jake")
8.1.2 实参和形参
在上述函数中,usename为形参,用于传递函数完成工作时所需要的信息。“jake”是一个实参,实参是 调用函数时传递给函数的信息。
8.2 传递实参
向函数传递实参的方法有很多,可以使用位置实参或关键字实参,传递的参数可使用列表和字典
8.2.1 位置实参
使用位置实参是,传递的实参要与函数定义的形参所匹配。
例如:
❶ def describe_pet(animal_type, pet_name):
"""显示宠物的信息"""
print("\nI have a " + animal_type + ".") _
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
❷ describe_pet('hamster', 'harry')
注意:如果使用位置实参,要注意实参的顺序是否正确,若不正确,结果可能出乎意料
8.2.2 关键字实参
使用关键字实参时,使用的是通过将形参赋值从而将值传递
例如:
def describe_pet(animal_type, pet_name):
"""显示宠物的信息"""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet(animal_type='hamster', pet_name='harry')
注意:使用关键字实参时,务必准确地指定函数定义中的形参名。
8.2.3 默认值
在编写函数时,可给每个形参指定默认值。在给形参指定了默认值后,可在调用函数时省略相应的实参。
例如:
def describe_pet(pet_name, animal_type='dog'):
"""显示宠物的信息"""
print("\nI have a " + animal_type + ".") _
print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet(pet_name='willie')
注意:在使用了默认值后,函数调用方式是属于位置调用。因此,在调用函数时,应先将未赋值的形参赋值。
8.2.4 等效的函数调用
在调用函数时,一下这几种方式等价。
def describe_pet(pet_name,animal_type ='dog'):
调用方式如下:
describe_pet("wilie")
describe_pet(jpet_name = "willie")
describe_pet(pet_name = 'harrt',animal_type ='hamster')
8.2.5 避免实参错误
使用函数时,可能出现实参错误,错误示例如下:
Traceback (most recent call last):
❶ File "pets.py", line 6, in
❷ describe_pet()
❸ TypeError: describe_pet() missing 2 required positional arguments: 'animal_type' and 'pet_name'
8.3 返回值
8.3.1 返回简单值
要使函数有返回值,使用return语句来使函数获取返回值。
例如:
❶ def get_formatted_name(first_name, last_name):
"""返回整洁的姓名"""
❷ full_name = first_name + ' ' + last_name
❸ return full_name.title()
❹ musician = get_formatted_name('jimi', 'hendrix')
print(musician)
8.3.2 让实参变成可选的
如果要让实参变成可选的,可以让形参变为默认值来实现。
例如:
❶ 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)
注意:在Python中,Python将非空字符串解释为True。
8.3.3 返回字典
函数可以返回任何类型的值。包括列表和字典等比较复杂的数据类型。
例如:
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)
8.3.4 结合使用函数和while循环
函数可以与Python中的任意结构结合起来。
例如:Python与while循环的结合
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 + "!")
8.4 传递列表
8.4.1 在函数中修改列表
将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,这让你能够高效地处理大量的数据。
例如:
❶ 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)
8.4.2 禁止函数修改列表
若要禁止函数修改列表,可以将列表副本传递给函数,以防止函数修改列表,但若传递的是副本,则运行时间将更长。
要将列表的副本传递给函数,可以像下面这样做:
function_name(list_name[:])
8.5 传递任意数量的实参
在Python中,可以使用 * +形参名让Python创建一个空元组,可以使用 ** + 形参让Python创建一个空字典
例如:
def make_pizza(*toppings):
形参名*toppings 中的星号让Python创建一个名为toppings 的空元组,并将收到的所有值都封装到这个元组中。
def build_profile(first, last, **user_info):
形参**user_info 中的两个星号让Python创建一个名为user_info 的 _ 空字典,并将收到的所有名称—值对都封装到这个字典中。
8.5.1 结合使用位置实参和任意数量实参
如果要让函数接受不同类型的实参,使用了多个实参,需要将形参定义为 * + 形参,而且必须在函数定义中将接纳任意数量实参的形参放在最后
例如:
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')
8.5.2 使用任意数量的关键字实参
在Python中,要使用任意数量的关键字实参,需要使用 ** + 形参将其获取,而将这些键值对存储到由形参构成的字典中,
例如:
def make_car(making,type,**inf): profile = {} profile["making"] = making profile["type"] = type for key, value in inf.items(): profile[key] = value return profile car = make_car('subaru', 'outback', color='blue', tow_package=True) print(car)
8.6 将函数存储在模块中
在Python中,为什么要将函数存储到模块中了,是因为将函数存贮到模块中,可以将函数代码的细节隐藏。
8.6.1 导入整个模块
要让函数是可导入的,得先创建模块。模块是扩展名为.py的文件。
要导入整个模块,可以使用一下方式:
import module_name
要调用模块名中的函数,使用一下方式:
module_name.function_name()
8.6.2 导入特定函数
要导入模块名中的特定函数,可使用一下方式:
from module_name import function_0, function_1, function_2
调用方式:
function_0
8.6.3 使用as给函数指定别名
如果要导入的函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的别名——函数的另一个名称,类似于外号。要给函数指定这种特殊外号,需要在导入它时这样做。
通用语法:
from module_name import function_name as fn
8.6.4 使用as给模块指定别名
给模块指定别名的通用语法如下:
import module_name as mn
8.6.5 导入模块中的所有函数
在Python中,要导入模块中的所有函数。可以使用星号(* )运算符可让Python导入模块中的所有函数。
例如:from pizza import *
导入后,直接使用函数名,而不需要模块名.函数名
注意:对于模块的导入,最佳的做法是,要么只导入你需要使用的函数,要么导入整个模块并使用句点表示法。
8.7 函数编写指南
在编写函数时,应注意一下细节:
- 给函数指定描述性名称时,只在其中使用小写字母和下划线
- 每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面,并采用文档字符串格式
- 给形参指定默认值时,等号两边不要有空格,函数调用中的关键字实参也应遵守
- 若形参很多,可使用一下方法
def function_name( _
parameter_0, parameter_1, parameter_2,
parameter_3, parameter_4, parameter_5):
function body...
8.8 小结
在本章中
- 介绍了如何定义函数,如何传递实参
- 介绍了如何使用位置实参和关键字实参,以及如何接受任意数量的实参
- 介绍了函数如何显示输出和函数如何实现返回值
- 介绍了如何将函数同列表、字典、if 语句和while 循环结合起来使用
- 介绍了如何将函数存储在被称为 模 模 块 模 模 的独立文件中,让程序文件更简单、更易于 理解
- 介绍了函数编写指南