Python-8.1-函数
- 函数
- 一:定义函数
- 1、向函数传递信息
- 2、实参和形参
- 二:传递实参
- 1、位置实参
- (1)调用函数多次
- (2)位置实参的顺序很重要
- 2、关键字实参
- 3、默认值
- 4、等效的函数调用
- 5、避免实参错误
- 三:返回值
- 1、返回简单值
- 2、让实参变为可选的
- 3、返回字典
- 4、结合使用函数和while循环
- 四:传递列表
- 1、在函数中修改列表
- 2、禁止函数修改列表
- 五:传递任意数量的实参
- 1、结合使用位置实参和任意数量实参
- 2、使用任意数量的关键字实参
- 六:将函数存储在模块中
- 1、导入整个模块
- 2、导入特定的函数
- 3、使用as给函数指定别名
- 4、使用as给模块指定别名
- 5、导入模块中的所有函数
- 七:函数编写指南
- 八:小结
函数
- 学习编写函数
- 学习向函数传递信息的方式
- 学习如何编写主要任务是显示信息的函数,还有用于处理数据并返回一个或一组值的函数
- 学习如何将函数存储在被称为模块的独立文件中,让主程序文件的组织更为有序
一:定义函数
- 函数是带名字的代码块,用于完成具体的工作
- 要执行函数定义的特定任务,可调用该函数
- 需要在程序中多次执行同一项任务时,无需反复编写完成该任务的代码,而只需调用执行该任务的函数,让Python运行其中的代码
- 通过使用函数,程序的编写、阅读、测试和修复都将更容易
1、向函数传递信息
#使用关键字def定义一个函数
#定义一个变量username
def user(username):
#函数体内执行的代码
print("Hello , " + username.title() + ".")
#调用函数user(),给username指定一个值jack
user('jack')
Hello , Jack.
2、实参和形参
- 参数:负责给函数传递一些必要的数据或者信息
- 形参
- 在函数定义的时候用到的参数,没有具体值,只是一个占位符号
- 在函数user()中,username是一个形参
- 实参
- 在调用函数的时候输入的值
- 在代码user(‘jack’)中,值‘jack’是实参
- 我们调用函数时,将要让函数使用的信息放在括号内
- 在user(‘jack’)中,将实参’jack’传递给了函数user(),这个值被存储在形参username中
#形参和实参的案例
def research(fl_name):
print("{} , what is your favorite fruit? ".format(fl_name))
print("{} , do you like apple? ".format(fl_name))
name = 'jake'
research(name.title())
Jake , what is your favorite fruit?
Jake , do you like apple?
二:传递实参
- 鉴于函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参
- 向函数传递实参的方式很多
- 位置实参
- 要求实参的顺序与形参的顺序相同
- 关键字实参
- 每个实参都是由变量名和值组成
- 使用列表和字典
1、位置实参
- 调用函数时,Python必须将函数调用的每个实参关联到函数定义中的一个形参
- 最简单的关联方式是基于实参的顺序
# 位置实参案例
def name_fruit(name , fruit):
print("Name : " + str(name.title()) +
"\nFavourite fruit : " + str(fruit.title()))
name_fruit('jack','apple')
Name : Jack
Favourite fruit : Apple
(1)调用函数多次
- 可以根据需要调用函数多次
- 调用函数是一种效率极高的工作方式
- 在函数中,可根据需要使用任意数量的位置实参,Python将按顺序将函数调用中的实参关联到函数定义中的相应的形参
#调用多次函数案例
def name_fruit(name , fruit) :
print("\nName : " + str(name.title()) +
"\nFavorite fruit : " + str(fruit.title()))
#可对函数多次调用
name_fruit('jack' , 'apple')
name_fruit('tony' , 'banana')
Name : Jack
Favorite fruit : Apple
Name : Tony
Favorite fruit : Banana
(2)位置实参的顺序很重要
- 使用位置参数来调用函数时,位置参数的顺序很重要
#位置实参顺序案例
def name_fruit(name , fruit):
print("Name : " + str(name.title()) +
"\nFavourite fruit : " + str(fruit.title()))
#位置实参的顺序不对,导致与预期结果不一
name_fruit('apple' , 'jack')
Name : Apple
Favourite fruit : Jack
2、关键字实参
- 关键字实参是传递给函数的名称-值对
- 使用关键字实参时,务必准确地指出函数定义的形参名
- 直接在参数中将名称和值相关联起来,向函数传递实参时不会混淆
- 关键字实参让你无需考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途
#关键字实参案例
def name_fruit(name , fruit):
print("Name : " + str(name.title()) +
"\nFavourite fruit : " + str(fruit.title()))
name_fruit(fruit = 'apple' , name = 'jack')
Name : Jack
Favourite fruit : Apple
3、默认值
- 编写函数时,可给每个形参指定默认值
- 在调用函数中给形参提供了实参时,Python将使用指定的实参值;否则,将使用形参的默认值
- 给形参指定默认值后,可在函数调用中省略相应的实参
- 使用默认值时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的形参
- 能让Python依然能够正确解读位置实参
# 默认值案例
def name_fruit(name , fruit='apple'):
print("Name : " + str(name.title()) +
"\nFavourite fruit : " + str(fruit.title()))
name_fruit(name='jack')
Name : Jack
Favourite fruit : Apple
4、等效的函数调用
- 鉴于可混合使用位置实参、关键字实参和默认值,通常有多种的等效函数调用方式
# 等效的函数调用
def name_fruit(name, fruit):
print("\nName : " + str(name.title()) +
"\nFavorite fruit : " + str(fruit.title()))
#下面三个对这个函数的所有调用都可行
name_fruit('jack','apple')
name_fruit(name='jack', fruit='apple')
name_fruit(fruit='apple', name='jack')
Name : Jack
Favorite fruit : Apple
Name : Jack
Favorite fruit : Apple
Name : Jack
Favorite fruit : Apple
5、避免实参错误
- 开始使用函数后,如果遇到实参不匹配错误,不要大惊小怪
- 你提供的实参多于或少于函数完成其工作所需的信息时,将出现实参不匹配错误
三:返回值
- 函数并非总是直接显示输出,相反,它可以处理一些数据,并返回一个或一组值
- 函数返回的值被称为返回值
- 在函数中,可使用return语句将值返回到调用函数的代码行
- 如果没有值需要返回,我们推荐使用return None表示函数结束
- 函数一旦执行return,则函数立即结束
- 返回值让你能够将程序的大部分繁重的工作移到函数中去完成,从而简化主程序
1、返回简单值
# 返回值案例
def get_formatted_name(frist_name, last_name):
"""返回整洁的名字"""
full_name = frist_name + ' ' + last_name
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)
Jimi Hendrix
2、让实参变为可选的
- 有时候,需要让实参变为可选的,这样使用函数的人就只需在必要时才提供额外的信息
- 可使用一个默认值“空字符串”让实参变成可选的
- Python将非空字符串解读为True
# 在函数定义中最后列出中间名的形参,并将其默认值设为空字符串
def get_formatted_name (frist_name , last_name ,middle_name = ''):
"""返回整洁的名字"""
#Python将非空字符串解读为True
if middle_name :
full_name = frist_name + ' ' + middle_name + ' ' + last_name
else :
full_name = frist_name + ' ' + last_name
#将其返回到函数调用行
return full_name.title()
#将返回的值存入到变量中
musician = get_formatted_name("john" , "lee" ,"hooker")
print(musician)
John Hooker Lee
3、返回字典
- 函数可以返回任何类型的值,包括列表和字典等较复杂的数据结构
# 新增可选形参,将其默认值设置为空字符串
def identify(frist_name , last_name , age='') :
"""返回一个字典,其中包含一个人的信息"""
person = {
"frist" : frist_name,
"last" : last_name
}
if age :
person['age'] = age
return person
musician = identify("jimi","hendrix" , 8)
print(musician)
{‘frist’: ‘dd’, ‘last’: ‘s’, ‘age’: 8}
4、结合使用函数和while循环
- 可将函数同Python的任何结构结合起来使用
# 结合使用函数和while循环案例
def research(names,fruits):
"""返回整洁的姓名"""
full_name = names.title() + " favorite fruit is " + fruits + "."
return full_name
while True :
print("\nPlease tell me your name and your favorite fruit.")
name = input("Enter your name : ")
fruit = input("Enter your favorite fruit : ")
respond = research(name , fruit)
print(respond)
repeat = input("Would you like to let another person respond?(yes or no)")
if repeat == 'no' :
break
Please tell me your name and your favorite fruit.
Enter your name : jack
Enter your favorite fruit : apple
Jack favorite fruit is apple.
Would you like to let another person respond?(yes or no)yes
Please tell me your name and your favorite fruit.
Enter your name : tony
Enter your favorite fruit : banana
Tony favorite fruit is banana.
Would you like to let another person respond?(yes or no)no
四:传递列表
- 向函数传递列表很有用,这种列表包含的可能是名字、数字或复杂的对象
- 将列表传递给函数后,函数就能直接访问其内容
- 每个函数都应只负责一项具体的工作
- 编写函数时,如果发现它执行的任务太多,请尝试将这些代码划分到两个函数中
- 总是可以在一个函数中调用另一个函数,有助于将复杂的任务划分成一系列的步骤
# 传递列表的案例
def favorite_fruits(fruits):
"""询问是否喜欢某一个水果"""
for fruit in fruits:
print("Do you like " + fruit + "?\n")
return None
fruits = ['apple' , 'banana' , 'pear']
favorite_fruits(fruits)
Do you like apple?
Do you like banana?
Do you like pear?
1、在函数中修改列表
- 将列表传递给函数后,函数就可以对其进行修改
- 在函数中对这个列表所做的任何修改都是永久性的,能够更高效的处理大量的数据
# version1.0
sell_fruits = ['apple' , 'banana' , 'pear']
bought_fruits = [ ]
print("The fruits sold here are: ")
while sell_fruits :
buy_fruit = sell_fruits.pop()
print("\t" + buy_fruit.title())
bought_fruits.append(buy_fruit)
print("\nThe fruits we bought: ")
for bought_fruit in bought_fruits:
print("\t" + bought_fruit.title())
The fruits sold here are:
Pear
Banana
Apple
The fruits we bought:
Pear
Banana
Apple
# version2.0
def sold(sell_fruits , bought_fruits):
print("The fruits sold here are: ")
while sell_fruits :
buy_fruit = sell_fruits.pop()
print("\t" + buy_fruit.title())
bought_fruits.append(buy_fruit)
def buy(bought_fruits):
print("\nThe fruits we bought: ")
for bought_fruit in bought_fruits:
print("\t" + bought_fruit.title())
sell_fruits = ['apple' , 'banana' , 'pear']
bought_fruits = []
sold(sell_fruits , bought_fruits)
buy(bought_fruits)
The fruits sold here are:
Pear
Banana
Apple
The fruits we bought:
Pear
Banana
Apple
2、禁止函数修改列表
- 即便卖完所有水果,也要保留原先sell_fruits列表,以供备案
- 为解决这个问题,可向函数传递列表的是副本而不是原件
- 可使用切片表示法[:]创建副本
# version1.0
#使用切片表示法保留列表
def sold(sell_fruits , bought_fruits):
print("The fruits sold here are: ")
while sell_fruits :
buy_fruit = sell_fruits.pop()
print("\t" + buy_fruit.title())
bought_fruits.append(buy_fruit)
def buy(bought_fruits):
print("\nThe fruits we bought: ")
for bought_fruit in bought_fruits:
print("\t" + bought_fruit.title())
sell_fruits = ['apple' , 'banana' , 'pear']
bought_fruits = []
#使用切片表示法,保留列表
sold(sell_fruits[:] , bought_fruits)
buy(bought_fruits)
print(sell_fruits)
print(bought_fruits)
The fruits sold here are:
Pear
Banana
Apple
The fruits we bought:
Pear
Banana
Apple
[‘apple’, ‘banana’, ‘pear’]
[‘pear’, ‘banana’, ‘apple’]
# version2.0
#无需使用切片表示法保留列表
def sold(sell_fruis , bought_fruits):
print("The fruits sold here are:")
for sell_fruit in sell_fruits:
print("\t" + sell_fruit.title())
bought_fruits.append(sell_fruit)
def buy(bought_fruits):
print("\nThe fruits we bought:")
for bought_fruit in bought_fruits:
print("\t" + bought_fruit.title())
sell_fruits = ['apple' , 'banana' , 'pear']
bought_fruits = []
sold(sell_fruits , bought_fruits)
buy(bought_fruits)
print(sell_fruits)
print(bought_fruits)
The fruits sold here are:
Apple
Banana
Pear
The fruits we bought:
Apple
Banana
Pear
[‘apple’, ‘banana’, ‘pear’]
[‘apple’, ‘banana’, ‘pear’]
五:传递任意数量的实参
- 有时候,你预先不知道函数需要接受多少个实参,好在Python允许函数从调用语句中收集任意数量的实参
- 形参名*fruits中的星号让Python创建一个名为fruits的空元组,并将收到的所有值都封装到这个元组中
# 传递任意数量的实参
def favorite_fruits(*fruits):
"""打印喜欢的水果"""
print("\nFavorite Fruit:")
for fruit in fruits:
print("\t" + fruit.title())
# 一个值调用函数的情形
favorite_fruits('apple')
# 多个值调用函数的情形
favorite_fruits('banana' , 'pear')
Favorite Fruit:
Apple
Favorite Fruit:
Banana
Pear
1、结合使用位置实参和任意数量实参
- 如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后
- Python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中
# 结合使用位置实参和任意数量实参案例
def favorite_fruits(person , *fruits):
"""打印喜欢的水果"""
person = int(person)
if person <= 1 :
print("\nIf " + str(person) + " people , The favorte is :")
else:
print("\nIf " + str(person) + " people , The favorte are :")
for fruit in fruits :
print("\t" + fruit )
favorite_fruits(1 , "apple")
favorite_fruits(2 , "banana" , "pear")
If 1 people , The favorte is :
apple
If 2 people , The favorte are :
banana
pear
2、使用任意数量的关键字实参
- 有时候,需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息
- 在这种情况下,可将函数编写成能够接受任意数量的键—值对
- 调用语句提供多少就接受多少
- 形参** el_fruits中的两个星号让Python创建一个名为el_fruit的空字典,并将收到的所有名称—值对都封装到这个字典中
# 使用任意数量的关键字实参
def fruits(name , color ,**el_fruits):
fruit = {}
fruit['fruit'] = name
fruit['color'] = color
for key , value in el_fruits.items():
fruit[key] = value
return fruit
re = fruits("apple" , "red" , size = "big" , price = "5")
print(re)
{‘fruit’: ‘apple’, ‘color’: ‘red’, ‘size’: ‘big’, ‘price’: ‘5’}
六:将函数存储在模块中
- 函数的优点之一是,使用它们可以将代码与主程序分离
- 将函数存储在被称为模块的独立文件中,再将模块导入到主程序中
- import语句允许在当前运行的程序中使用模块中的代码
- 通过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上
- 能让你在众多不同的程序中重用函数
- 将函数存储在独立文件中,可与其他程序员共享这些文件而不是整个程序
1、导入整个模块
- 要让函数是可导入的,得先创建模块
- 模块是扩展名为.py的文件,包含要导入到程序中的代码
#下面来创建一个包含函数name_fruit()的模块,将文件名设置为fruit.py
def name_fruit(name , fruit):
"""打印每个人喜欢的水果"""
print(name.title() + " favorite fruit is " + fruit + '.')
return None
# 接下来,我们在fruit.py所在的目录中创建一个名为favorite_fruit.py的文件
# 这个文件导入刚创建的模块,再调用name_fruit()两次
import fruit
fruit.name_fruit('jack' , 'apple')
fruit.name_fruit('tony' , 'banana')
Jack favorite fruit is apple.
Tony favorite fruit is banana.
2、导入特定的函数
- 可以导入模块中的特定函数
# 可以导入模块中特定函数,这种导入方法的语法如下:
from module_name import function_name
# 通过用逗号分隔函数名,可根据需要从模块中导入任意数量的函数
from module_name import function_0, function_1, function_2
3、使用as给函数指定别名
- 如果要导入的函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简单而独一无二的别名
- 要给函数指定这种特殊外号,需要在导入时,利用关键字为你提供别名
# 给函数指定别名的通用语法如下
from module_name import function_name as fn
module_name.fn()
4、使用as给模块指定别名
- 你还可以给模块指定别名,能够更轻松地调用模块中的函数
# 给模块指定别名的通用语法如下
import module_name as mn
mn.function_name()
5、导入模块中的所有函数
- 使用星号(*)运算符可让Python导入模块中所有函数
- 不推荐使用此方法
- 要么只导入你需要使用的函数,要么导入整个模块并使用句点表示法
# 导入模块中所有函数的通用语法如下
from module_name import *
七:函数编写指南
- 编写函数时,应给函数指定描述性名称,且只在其中使用小写字母和下划线
- 每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面,并采用文档字符串格式
- 文档良好的函数让其他程序员只需阅读文档字符串中的描述就能够使用它
- 他们完全可以相信代码如描述的那样运行
- 只要知道函数的名称、需要的实参以及返回值的类型,就能在自己的程序中使用它
# 给形参指定默认值时,等号两边不要有空格:
def function_name(parameter_0, parameter_1='default value')
# 对于函数调用中的关键字实参,也应遵循这种约定
function_name(value_0, parameter_1='value')
- PEP 8建议代码行的长度不要超过79字符,这样只要编辑器窗口适中,就能看到整行代码
- 如果形参过多,可在函数定义中输入左括号后按回车键,并在下一行按两次Tab键,从而将形参列表和只缩进一层的函数体区分开来
def function_name(
parameter_0, parameter_1, parameter_2,
parameter_3, parameter_4, parameter_5):
function body...
- 如果程序或模块包含多个函数,可使用两个空行将相邻的函数分开
- 更容易知道前一个函数在什么地方结束,下一个函数从什么地方开始
- 所有的import语句都应放在文件开头,唯一例外的情形是,在文件开头使用注释来描述整个程序
八:小结
- 编写函数,以及如何传递实参,让函数能够访问完成其工作所需的信息
- 使用位置实参和关键字实参,以及接受任意数量的实参
- 显示输出的函数和返回值的函数
- 将函数同列表、字典、if语句和while循环结合起来使用
- 将函数存储在被称为模块的独立文件中,让程序文件更简单、更易于理解
- 函数的编写指南,遵循这些指南可让程序始终结构良好,易于阅读