第8章. 函数

  • 8.1 定义函数
  • 8.1.1 向函数传递信息
  • 8.1.2 实参和形参
  • 8.2 传递实参
  • 8.2.1 位置实参
  • 8.2.2 关键字实参
  • 8.2.3 默认值
  • 8.2.4 等效的函数调用
  • 8.2.5 避免实参错误
  • 8.3 返回值
  • 8.3.1 返回简单值
  • 8.3.2 让实参变成可选的
  • 8.3.3 返回字典
  • 8.3.4 结合使用函数和 while 循环
  • 8.4 传递列表
  • 8.4.1 在函数中修改列表
  • 8.4.2 禁止函数修改列表
  • 8.5 传递任意数量的实参
  • 8.5.1 结合使用位置实参和任意数量实参
  • 8.5.2 使用任意数量的关键字实参
  • 8.6 将函数存储在模块中
  • 8.6.1 导入整个模块
  • 8.6.2 导入特定的函数
  • 8.6.3 使用 as 给函数指定别名
  • 8.6.4 使用 as 给模块指定别名
  • 8.6.5 导入模块中的所有函数
  • 8.7 函数编写指南

 

  • 8.1 定义函数 
1 def greet_user():
2     """显示简单的问候语"""  # 文档字符串 的注释,文档字符串三括号引起
3     print("Hello!")
4 
5 greet_user()

res:

  

  关键字 def 告诉 Python,你要定义一个函数。函数定义以冒号结尾。紧跟在 def greet_user(): 后面的所有缩进行构成了函数体

 

  • 8.1.1 向函数传递信息
1 def greet_user(username):
2     """显示简单的问候语"""
3     print(f"Hello, {username.title()}!")
4 
5 greet_user('jesse')

res:

  

 

  • 8.1.2 实参和形参

  在 8.1.1 的函数 greet_user() 的定义中,变量 username 是一个形参,即函数完成工作所需的信息。在代码 greet_user('jesse') 中,值 'jesse' 是一个实参,即调用函数时传递给函数的信息。调用函数时,将要让函数使用的信息放在圆括号内。在 greet_user('jesse') 中,将实参 'jesse' 传递给了函数 greet_user() ,这个值被赋给了形参 username

 

  • 8.2.1 位置实参

  调用函数时,Python 必须将函数调用中的每个实参都关联到函数定义中的一个形参。为此,最简单的关联方式是基于实参的顺序。这种关联方式称为位置实参。

1 def describe_pet(animal_type,pet_name):
2     """显示宠物的信息"""
3     print(f"\nI have a {animal_type}.")
4     print(f"My {animal_type}'s name is {pet_name.title()}.")
5 
6 describe_pet('hamster','harry')

res:

  

 

  位置实参的顺序很重要

 

  • 8.2.2 关键字实参

  关键字实参是传递给函数的名称值对。因为直接在实参中将名称和值关联起来,所以向函数传递实参时不会混淆。关键字实参让你无须考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。

1 def describe_pet(animal_type,pet_name):
2     """显示宠物的信息"""
3     print(f"\nI have a {animal_type}.")
4     print(f"My {animal_type}'s name is {pet_name.title()}.")
5 
6 describe_pet(pet_name='harry',animal_type='hamster')

 res:

  

 

  • 8.2.3 默认值

  编写函数时,可给每个形参指定默认值。在调用函数中给形参提供了实参时,Python 将使用指定的实参值;否则,将使用形参的默认值。因此,给形参指定默认值后,可在函数调用中省略相应的实参。

  使用默认值时,必须先在形参列表中列出没有默认值的形参,再列出有默认值的实参。这让 Python 依然能够正确地解读位置实参。(如果形参列表的第一个形参 有默认值 而 第二个形参 没有默认值,当使用‘位置实参’时,如果只有一个实参,那么这个仅有的实参将传递给第一个形参(有默认值的),与我们想要的效果不一致

1 def describe_pet(pet_name,animal_type='dog'):
2     """显示宠物的信息"""
3     print(f"\nI have a {animal_type}.")
4     print(f"My {animal_type}'s name is {pet_name.title()}.")
5 
6 describe_pet(pet_name='willie')
7 describe_pet('willie')

res:

  

 

  • 8.3 返回值

  函数返回的值称为返回值。在函数中,可使用 return 语句将值返回到调用函数的代码行。

 

  • 8.3.1 返回简单值
1 def get_formatted_name(first_name,last_name):
2     """返回整洁的姓名"""
3     full_name = f"{first_name} {last_name}"
4     return full_name.title()
5 
6 musician = get_formatted_name('jimi','hendrix')
7 print(musician)

res:

  

 

  • 8.3.2 让实参变成可选的

(下面这个例子,为了让 get_formatted_name() 在没有提供中间名时依然可行,可将形参 middle_name 的默认值设置为空字符串,并将其移到形参列表的末尾)

 1 def get_formatted_name(first_name,last_name,middle_name=''):
 2     """返回整洁的姓名"""
 3     if middle_name: # 如果 middle_name 不为空
 4         full_name = f"{first_name} {middle_name} {last_name}"
 5     else:
 6         full_name = f"{first_name} {last_name}"
 7     return full_name.title()
 8 
 9 musician = get_formatted_name('jimi','hendrix')
10 print(musician)
11 
12 musician = get_formatted_name('john','hooker','lee')
13 print(musician)

 res:

  

  Python 将非空字符串解读为 True。如果没有提供 middle_name,middle_name 将为空字符串,导致 if 测试未通过。

 

  • 8.3.3 返回字典

  函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。

1 def build_person(first_name,last_name,age = None):
2     """返回一个字典,其中包含有关一个人的信息。"""
3     person = {'first':first_name,'last':last_name}
4     if age:
5         person['age'] = age
6     return person
7 
8 musician = build_person('jimi','hendrix',age = 27)
9 print(musician)

 res:

  

  在条件测试中,None 相当于 False

 

  • 8.4 传递列表
1 def greet_users(names):
2     """向列表中的每位用户发出简单的问候。"""
3     for name in names:
4         msg = f"Hello, {name.title()}!"
5         print(msg)
6 
7 usernames = ['hannah','ty','margot']
8 greet_users(usernames)

res:

  

 

  • 8.4.1 在函数中修改列表

  将列表传递给函数后,函数就可以对其进行修改。在函数中对这个列表所做的任何修改都是永久性的

 1 def print_models(unprinted_designs,completed_models):
 2     """
 3     模拟打印每个设计,直到没有未打印的设计为止
 4     打印每个设计后,都将其移到列表 completed_models 中
 5     """
 6     while unprinted_designs:
 7         current_design = unprinted_designs.pop()
 8         print(f"Printign model: {current_design}")
 9         completed_models.append(current_design)
10 
11 def show_completed_models(completed_models):
12     """显示打印好的所有模型"""
13     print("\nThe following models have been printed:")
14     for completed_model in completed_models:
15         print(completed_model)
16 
17 unprinted_designs = ['phone case','robot pendant','dodecahedron']
18 completed_models = []
19 
20 print_models(unprinted_designs,completed_models)
21 show_completed_models(completed_models)

res:

  

 

  • 8.4.2 禁止函数修改列表

  有时候,需要禁止函数修改列表。为解决这个问题,可向函数传递列表的副本而非原件。

  要将列表的副本传递给函数,可以想下面这样做:

function_name(list_name[:])

 例如 8.4.1 中,将

1 print_models(unprinted_designs,completed_models)

改为:

1 print_models(unprinted_designs[:],completed_models)

 

  • 8.5 传递任意数量的实参
1 def make_pizza(*toppings):
2     """打印顾客点的所有配料。"""
3     print(toppings)
4 
5 make_pizza('pepperoni')
6 make_pizza('mushrooms','green peppers','extra cheese')

res:

  

  形参名 *toppings 中的星号让 Python 创建一个名为 toppings 的空元组,并将收到的所有值都封装到这个元组中。

1 def make_pizza(*toppings):
2     """概述要制作的比萨。"""
3     print("\nMaking a pizza with the following toppings:")
4     for topping in toppings:
5         print(f"- {topping}")
6 
7 make_pizza('pepperoni')
8 make_pizza('mushrooms','green peppers','extra cheese')

res:

  

 

  • 8.5.1 结合使用位置实参和任意数量实参

  如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。Python 先匹配位置实参和关键字实参再将余下的实参都收集到最后一个形参中

1 def make_pizza(size, *toppings):
2     """概述要制作的比萨。"""
3     print(f"\nMaking a {size}-inch pizza with the following toppings:")
4     for topping in toppings:
5         print(f"- {topping}")
6 
7 make_pizza(16,'pepperoni')
8 make_pizza(12,'mushrooms','green peppers','extra cheese')

res:

  

  基于上述函数定义,Python 将收到的第一个值赋给形参 size,并将其他所有值都存储在元组 toppings 中。

 

  • 8.5.2 使用任意数量的关键字实参

  有时候,需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息。在这种情况下,可将函数编写成能够接受任意数量的键值对——调用语句提供了多少就接受多少。

 1 def build_profile(first,last,**user_info):
 2     """创建一个字典,其中包含我们知道的有关用户的一切。"""
 3     user_info['first_name'] = first
 4     user_info['last_name'] = last
 5     return user_info
 6 
 7 user_profile = build_profile('albert','einstein',
 8                              location = 'princeton',
 9                              field = 'physics')     # 注意,后面两个键“location”和“field”都没有用引号引起来
10 print(user_profile)

res:

  

  函数 build_profile() 的定义要求提供名和姓,同时允许根据需要提供任意数量的名称值对。形参 **user_info 中的两个星号让 Python 创建一个名为 user_info 的空字典,并将收到的所有名称值对都放到这个字典中。(一个星号,空元组;两个星号,空字典

 

  • 8.6 将函数存储在模块中

  可以将函数存储在称为模块的独立文件中,再将模块导入到主程序中。import 语句允许在当前运行的程序文件中使用模块中的代码。

 

  • 8.6.1 导入整个模块

  要让函数是可导入的,得先创建模块。模块是扩展名为.py 的文件,包含要导入到程序中的代码。

一个示例:

pizza.py:

1 def make_pizza(size, *toppings):
2     """概述要制作的比萨。"""
3     print(f"\nMaking a {size}-inch pizza with the following toppings:")
4     for topping in toppings:
5         print(f"- {topping}")

making_pizzas.py:

1 import pizza
2 
3 pizza.make_pizza(16,'pepperoni')
4 pizza.make_pizza(12,'mushrooms','green peppers','extra cheese')

运行 making_pizzas.py:

  

 

  这就是一种导入方法:只需编写一条 import 语句并在其中指定模块名,就可在程序中使用该模块中的所有函数。如果使用这种 import 语句导入了名为 module_name.py 的整个模块,就可使用下面的语法来使用其中任何一个函数:

module_name.function_name()

 

  • 8.6.2 导入特定的函数

  还可以导入模块中的特定函数,这种导入方法的语法如下:

from module_name import function_name

  通过用逗号分隔函数名,可根据需要从模块中导入任意数量的函数:

 

from module_name import function_0, function_1, function_2

示例(对于前面的 making_pizzas.py):

1 from pizza import make_pizza  # 显然,函数名后面不用加参数列表
2 
3 make_pizza(16,'pepperoni')
4 make_pizza(12,'mushrooms','green peppers','extra cheese')

  使用这种语法时,调用函数时无须使用句点。由于在 import 语句中显式地导入了函数 make_pizza(),调用时只需指定其名称即可。

 

  • 8.6.3 使用 as 给函数指定别名

示例:

1 from pizza import make_pizza as mp
2 
3 mp(16,'pepperoni')
4 mp(12,'mushrooms','green peppers','extra cheese')

  指定别名的通用语法如下:

from mudule_name import function_name as fn

 

  • 8.6.4 使用 as 给模块指定别名

示例:

1 import pizza as p 
2 
3 p.make_pizza(16,'pepperoni')
4 p.make_pizza(12,'mushrooms','green peppers','extra cheese')

  给模块指定别名的通用语法如下:

import module_name as mn

 

  • 8.6.5 导入模块中的所有函数

  使用星号*)运算符可让 Python 导入模块中的所有函数。

1 from pizza import *
2 
3 make_pizza(16,'pepperoni')
4 make_pizza(12,'mushrooms','green peppers','extra cheese')

  语法:

from module_name import *

 

  • 8.7 函数编写指南

  应给函数指定描述性名称,且只在其中使用小写字母和下划线。

  给形参指定默认值时,等号两边不要有空格。

def function_name(parameter_0, parameter_1='default value')

  对于函数调用中的关键字实参,也应遵循这种规定。

function_name(value_0, parameter_1='value')

(〃>_<;〃)(〃>_<;〃)(〃>_<;〃)

posted @ 2023-06-06 21:17  我会变强的  阅读(9)  评论(0编辑  收藏  举报