python入门基础(9)--函数及模块
函数是带名字的代码块,要执行函数定义的特定任务,可调用该函数。
需要在程序中多次执行同一项任务时,你无需反复编写完成该任务的代码,而只需调用执行该任务的函数,通过使用函数,程序的编写、阅读、测试和修复都将更容易。主程序文件的组织更为有序
一、如何定义一个函数
使用关键字 def 来定义一个函数。
def greeting_user(): print("Hello!,Welcome to Python World!") greeting_user()
如上述代码:第一行定义一个函数greeting_user,第二行为函数的功能,即打印字符串 "Hello!,Welcome to Python World!"
第三行,即调用函数greeting_user,作用就是打印字符串。
1)向函数传递信息
稍作修改,在函数定义 def greeting_user() 的括号内添加 username ,可让函数接受所给定 username 指定的任何值。
这个函数就可以调用给 username 指定一个值,调用 greeting_user() 时,可将一个名字传递给它,如下所示:
def greeting_user(username): print("Hello!,Welcome "+ username.title() + " use Python programing language!")
greeting_user('Bush')
greeting_user('Jack')
greeting_user('Lucy')
代码 greeting_user('Bush') 调用函数 greeting_user() ,并向它提供执行 print 语句所需的信息。这个函数接受你传递给它的名字
2)实参和形参
前面定义函数 greeting_user() 时,要求给变量 username 指定一个值。调用这个函数并提供这种信息(人名)时,它将打印相应的问候语。
在函数 greeting_user() 的定义中,变量 username 是一个形参—函数完成其工作所需的一项信息。
在代码 greeting_user('Bush') 中,值 'Bush'、‘Jack’、‘Lucy’ 是一个实参。实参是调用函数时传递给函数的信息,也即这几个字符串,会被传递给形参 username。
调用函数时,将要让函数使用的信息放在括号内。在greeting_user('Bush') 中,将实参'Bush' 传递给了函数 greeting_user() ,这个值被存储在形参 username 中。
二、实参
1)位置实参
由于通常函数中,会存在多个形参,调用函数时,Python必须将函数调用中的每个实参都关联到函数定义中的一个形参。为此,最简单的关联方式是基于实参的顺序。这种关联方式被称为位置实参。
def my_pet(animal_type, pet_name): print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") my_pet('dog', 'Wangcai')
上述代码中,my_pet()函数中存在两个形参,即animal_type和pet_name,也就是在调用函数my_pet()时,需要2个参数,即在my_pet('dog', 'Wangcai')中,将‘dog’存入到animal_type中,‘Wangcai’存入到pet_name中,并在my_pet()中的两个print语句中进行调用 。
注意:使用位置实参来调用函数时,如果实参的顺序不正确,结果会出错。
2)关键字实参
关键字实参是传递给函数的名称-值对。直接在实参中将名称和值关联起来,函数传递实参时不会混淆。关键字实参让你无需考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。
my_pet(animal_type='dog', pet_name='Wangcai') my_pet(pet_name='Xiaoqiang',animal_type='cockroach')
函数 my_pet() 还是原来那样,但调用这个函数时,向Python明确地指出了各个实参对应的形参。注意:上述两个形参位置改变,在赋值的情况下,不影响程序运行。
运行结果
I have a dog. My dog's name is Wangcai. I have a cockroach. My cockroach's name is Xiaoqiang.
3)默认值
编写函数时,可给每个形参指定默认值。如果在调用函数中给形参提供了实参,Python将使用指定的实参值;否则,将使用形参的默认值。因此,给形参指定默认值后,可在函数调用中省略相应的实参
def my_new_pet(new_pet_name,new_animal_type='dog'): print("\nI have a " + new_animal_type + ".") print("My " + new_animal_type + "'s name is " + new_pet_name.title() + ".") my_new_pet(new_pet_name='Wangcai') my_new_pet(new_pet_name='Xiaoqiang') my_new_pet(new_pet_name='Xiaoqiang',new_animal_type='cockroach')
运行结果:
I have a dog. My dog's name is Wangcai. I have a dog. My dog's name is Xiaoqiang. I have a cockroach. My cockroach's name is Xiaoqiang.
第一、二个my_new_pet()函数调用只给定了两个名字,没有给定动物类型,则函数采用默认类型‘dog’,第三个函数调用给定的new_animal_type='cockroach',则函数中两个打印调用给定的cockroach类型。
实际运行结果:
注意:可混合使用位置实参、关键字实参和默认值,通常有多种等效的函数调用方式,如上述
my_pet(animal_type='dog', pet_name='Wangcai') my_pet(pet_name='Xiaoqiang',animal_type='cockroach')
my_new_pet(new_pet_name='Wangcai') my_new_pet(new_pet_name='Xiaoqiang') my_new_pet(new_pet_name='Xiaoqiang',new_animal_type='cockroach')
三 ,函数的返回值
函数可以处理一些数据,并返回一个或一组数值,函数返回的值被称为返回值。在函数中,可使用 return 语句将值返回到调用函数的代码行。返回值能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序
1)返回简单值
def get_full_name(first_name, middle_name, last_name): #定义一个函数,有三个形参 full_name = first_name+' '+middle_name+' '+last_name #函数功能,将函数的三个形参进行连接 return full_name.title() #返回值 musician = get_full_name('Bush','lee', 'Alien') # 调用返回值的函数时,需要提供一个变量musician,用于存储返回的值 # 通过函数将Bush和Alien连接后,赋值给变量musician print(musician)
2)传递列表
向函数传递列表很有用,这种列表包含的可能是名字、数字或更复杂的对象(如字典),将列表传递给函数,函数就能直接访问其内容。
def menu_lists(menus): #定义一个函数,参数为列表 for menu in menus: #循环列表 msg = "The new menus is " + menu.title() + "!" print(msg) #打印列表 new_menus = ['Boiled meat', 'Spicy fish pieces', 'Chicken Feet with Pickled Peppers'] #定义一个列表 menu_lists(new_menus) #调用函数menu_lists,并将列表new_menus传递给menu_lists(menus)中的形参menus,并执行函数中的循环
(1)在函数中修改列表
将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,这让你能够高效地处理大量的数据。
completed_menus = [] #创建一个名为 completed_menus 的空列表 # 模拟打印每个设计,直到没有未打印的菜单为止 # 打印每个菜单后,都将其移到列表completed_menus中 while new_menus: current_menu = new_menus.pop() #pop,从列表new_menus末尾删除一个设计,并存放到变量名current_menu中 #模拟根据设计制作打印菜单的过程 print("Printing menu: " + current_menu) completed_menus.append(current_menu) #在列表completed_menus中,逐渐存入变量名current_menu的值 #下列代码打印new_menus print(new_menus) #打印出列表new_menus print("\nThe following menus have been printed:")# 显示打印好的所有菜单 for completed_menu in completed_menus: #for循环,打印出列表completed_menus print(completed_menu)
运行结果如下:
Printing menu: Chicken Feet with Pickled Peppers Printing menu: Spicy fish pieces Printing menu: Boiled meat [] The following menus have been printed: Chicken Feet with Pickled Peppers Spicy fish pieces Boiled meat
上述代码运行结果:
注:代码重组
在(1)函数中修改列表里列举的代码,有许多的重复功能 ,可以重新组织这些代码,编写两个函数,一个函数将负责处理打印菜单的工作,另一个将描写打印了哪些菜单。
#下述先定义两个函数 def print_menus(new_menus, completed_menus): #定义一个函数将负责处理打印菜单的工作 while new_menus: #当new_menus不为空 current_menu = new_menus.pop() #弹出 new_menus中最后一个元素,并赋值给变量current_menu #注意 pop()的顺序是反序,也即从最后一个元素开始,到第一个元素结束。 print("Printing menus: " + current_menu) completed_menus.append(current_menu) #列表completed_models逐渐增加 def show_completed_menus(completed_models): #定义函数,显示已打印了哪些菜单 print("\nThe following models have been printed:") for completed_model in completed_models: #for循环,打印出数列completed_models中的元素 print(completed_model) #定义一个列表,一个空表,再调用上述两个函数。 new_menus = ['Boiled meat', 'Spicy fish pieces', 'Chicken Feet with Pickled Peppers'] completed_menus = [] #创建一个空表 print_menus(new_menus, completed_menus) #调用第一个函数,打印菜单 show_completed_menus(completed_menus) #调用第2个函数,显示已完成菜单
运行结果:
Printing menus: Chicken Feet with Pickled Peppers Printing menus: Spicy fish pieces Printing menus: Boiled meat The following models have been printed: Chicken Feet with Pickled Peppers Spicy fish pieces Boiled meat
(2)禁止函数修改列表
在程序运行时,可能需要禁止函数修改列表。
编写了一个将这些移到打印好的菜单列表中的函数,可能会做出这样的决定:即便打印所有菜单后,也需要保留原来的未打印的菜单列表,以供备案。
例如,上述列表new_menus = ['Boiled meat', 'Spicy fish pieces', 'Chicken Feet with Pickled Peppers'],由于使用pop,将所有菜单都移出了new_menus,使得列表new_menus变成了空的,致使原有数据丢失(如上述运行结果第4行显示为[] )。
为解决此问题,可向函数传递列表的副本;这样函数所做的任何修改都只影响副本,而丝毫不影响原列表。切片表示法 [:] 创建列表的副本
#禁止函数修改列表 my_menus = ['meat', 'fish pieces', 'Chicken Feet'] print_menus(my_menus[:],completed_menus) print(my_menus) #重新打印列表my_menus,
如上述代码,重新定义一个列表my_menus ,调用重组后的函数print_menus,但参数只给定了my_menus[:]和completed_menus,最后重新打印列表my_menus ,检查是否是空列表。
运行结果如下:
Printing menus: Chicken Feet Printing menus: fish pieces Printing menus: meat ['meat', 'fish pieces', 'Chicken Feet']
3)传递任意数量的实参
当预先不知道函数需要接受多少个实参时,Python允许函数从调用语句中收集任意数量的实参。函数只有一个形参 *toppings ,但不管调用语句提供了多少实参,这个形参都将它们统统收入囊中
形参名 *toppings 中的星号让Python创建一个名为 toppings 的空元组,并将收到的所有值都封装到这个元组中
def make_menus(*toppings): print("\nMaking a menus with the following toppings:") for topping in toppings: print("- " + topping) make_menus('fish') make_menus('meat', 'fish', 'beef')
运行如下:
Making a menus with the following toppings: - fish Making a menus with the following toppings: - meat - fish - beef
(1)结合使用位置实参和任意数量实参
在函数定义中将接纳任意数量实参的形参放在最后。Python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中
def make_menus(size,*toppings): print("\nMaking a "+str(size)+" kilogram menus with the following toppings:") for topping in toppings: print("- " + topping) make_menus(2,'fish') make_menus(6,'meat', 'fish', 'beef')
运行结果如下:
Making a 2 kilogram menus with the following toppings: - fish Making a 6 kilogram menus with the following toppings: - meat - fish - beef
(2)使用任意数量的关键字实参
def get_person_info(given_name, family_name,**user_info): #定义一个函数,有三个形参 person_info={} #定义一个person_info person_info['first_name']=family_name #字典里的第一个key为first_name,赋值为形参中的given_name person_info['last_name']=given_name #字典里的第二个key为last_name,赋值为形参中的family_name for key,value in user_info.items(): person_info[key]=value return person_info user_info = get_person_info('albert','einstein',location='princetion',field = 'physics') print(user_info)
运行结果如下:
{'first_name': 'einstein', 'last_name': 'albert', 'location': 'princetion', 'field': 'physics'}
4)将函数存储在模块中
函数的优点:
一,可将代码块与主程序分离。通过给函数指定描述性名称,让主程序容易理解得多。
二、将函数存储在被称为模块的独立文件中,再将模块导入到主程序中。import 语句允许在当前运行的程序文件中使用模块中的代码。
通过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上,能让你在不同的程序中重用函数。
函数存储在独立文件中后,可与其他程序员共享这些文件而不是整个程序。知道如何导入函数还能让你使用其他程序员编写的函数库
1)导入整个模块
让函数是可导入的,创建模块。模块是扩展名为.py的文件,包含要导入到程序中的代码。如下图中的创建一个包含4个不同函数的 function 的模块
在mainframe中调用模块function及其中的函数
import function #导入模块function new_menus = ['Boiled meat', 'Spicy fish pieces', 'Chicken Feet with Pickled Peppers'] completed_menus = [] #创建一个空表 function.print_menus(new_menus, completed_menus) #调用模块function中的函数print_menus function.show_completed_menus(completed_menus) #调用模块function中的函数show_completed_menus #禁止函数修改列表 my_menus = ['meat', 'fish pieces', 'Chicken Feet'] function.print_menus(my_menus[:],completed_menus)#调用模块function中的函数print_menus function.make_menus(2,'fish') function.make_menus(6,'meat', 'fish', 'beef') user_info =function.get_person_info('albert','einstein',location='princetion',field = 'physics') #调用模块function中的get_person_info函数 print(user_info)
2)导入特定的函数
from function import print_menus,show_completed_menus #直接导入某模块中的特定函数, new_menus = ['Boiled meat', 'Spicy fish pieces', 'Chicken Feet with Pickled Peppers'] completed_menus = [] #创建一个空表 print_menus(new_menus, completed_menus) #调用函数print_menus show_completed_menus(completed_menus) #调用函数show_completed_menus
3) 使用 as 给模块指定别名
导入的函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的别名,类似于外号,在引用 的过程中,就相对比较方便
import function as func #给function指定一个短的名称func new_menus = ['Boiled meat', 'Spicy fish pieces', 'Chicken Feet with Pickled Peppers'] completed_menus = [] #创建一个空表 func.print_menus(new_menus, completed_menus) #调用函数print_menus func.show_completed_menus(completed_menus) #调用函数show_completed_menus
as 除了给模块指定别名,也可以给模块中的函数指定别名:
from function import print_menus as p_m from function import show_completed_menus as s_m new_menus = ['Boiled meat', 'Spicy fish pieces', 'Chicken Feet with Pickled Peppers'] completed_menus = [] #创建一个空表 p_m(new_menus, completed_menus) #调用函数print_menus s_m(completed_menus) #调用函数show_completed_menus
4)导入模块中的所有函数
from function import * new_menus = ['Boiled meat', 'Spicy fish pieces', 'Chicken Feet with Pickled Peppers'] completed_menus = [] #创建一个空表 print_menus(new_menus, completed_menus) #调用函数print_menus show_completed_menus(completed_menus) #调用函数show_completed_menus
注意区别:(1)在导入模块时,使用函数用法:function.print_menus(new_menus, completed_menus)
(2) 导入特定的函数时,使用函数用法:print_menus(new_menus, completed_menus)
(3)使用模块的别名时,使用函数用法:func.print_menus(new_menus, completed_menus)
import 开头导入的模块,在使用的时候需要带上模块的名称或别名( as 后面名称)
from model import * 这种类型的则不需要,可以直接调用函数。