1.定义一个函数
定义一个函数需要5个部分:
def
告诉Python,用户在自定义函数function_name
告诉Python要定义的函数的名字,且取名尽量做到descriptive(parameters)
这是形式参数,简称形参,接收函数调用时,传过来的实参,不需要传参时可省略'''docstring'''不执行任何功能,仅用来说明函数功能,调用函数者可以查看该函数的docstring以了解其功能
function_body
是函数的主体,函数要实现的功能由它决定
格式:
#函数定义def function_name(parameters): #注意冒号 '''docstring''' #注意缩进1个tab function_body #注意缩进1个tab#函数调用 function_name(arguments) #arguments为实参,字符串参数要加引号
2.参数
在上述的函数定义格式中,有两种参数,分别是:parameters和arguments
parameters为形式参数,简称为形参在函数定义时,仅作为符号,表示这里应该有这样一个参数,实现函数的成功定义。
arguments为实参,即主程序中,需要调用函数处理的实实在在的信息。调用时,会实现parameter_1=argument_1...,将所有实参的值赋给对应的形参,交由函数处理。
例:
输入:
def greet_user(username): '''display a simple greeting''' print('hello, '+username.title()+'!') greet_user('jack')
输出:
c:\py>function_define hello, Jack!
3.传送多个参数
上面的例子是仅传一个参数的情况,parameters和arguments可以有多个,有3种方法实现多参数传送。
(1) 位置实参
def语句
def function_name(parameter_1, parameter_2,..., parameter_n):
调用函数语句
function_name(argument_1, argument_2,..., argument_n):
调用函数语句中的实参与def语句中的形参按顺序一一对应,传参时实现的操作如下:
parameter_1=argument_1 parameter_2=argument_2 . . . parameter_n=argument_n
注意,使用位置实参时,一定要按照定义函数时,正确的顺序排列,不然会出错。
(2) 关键字实参
关键字传参是将一个name-value组合传给函数形参。
调用形式:function_name(name_1=value_1,name_2=value_2,...,name_n=value_n)
name-value里面,name为函数定义时,形参的名字,value为主程序中实参的值,通过name=value实现传参。所以通过关键字实参传参,并不需要按照定义时的顺序。
输入:
def describe_pet(animal_type,pet_name): '''display information about a pet''' print('\nI have a '+animal_type+'.') print('My '+animal_type+"'s name is "+pet_name+'.') describe_pet(animal_type='dog',pet_name='harry')#顺序不一样describe_pet(pet_name='harry',animal_type='dog')
输出:
c:\py>describe_pet.py I have a dog. My dog's name is harry. I have a dog. My dog's name is harry.
上面程序调用了两次describe_pet函数,参数顺序不一样,但是输出结果一样。
(3) 默认值
当一个函数被调用时,它的某些参数总是很少改变时,我们可以给这些很少变动的参数,在定义函数时,给它们一个默认值。这样在调用函数时,若与默认值相同,则可以不用写该参数的实参值,直接采用默认值,如果与默认值不符,可以用关键字name-value对传参。
输入:
def describe_pet(pet_name,animal_type='dog'): #默认animal_type参数值为‘dog’ '''display information about a pet''' print('\nI have a '+animal_type+'.') print('My '+animal_type+"'s name is "+pet_name+'.') describe_pet(pet_name='harry') #省略animal_type参数值describe_pet('harry') #采用位置实参传参describe_pet(animal_type='cat',pet_name='tom') #与默认值不符,用name-value对传参
输出:
c:\py>describe_pet.py I have a dog. My dog's name is harry. I have a dog. My dog's name is harry. I have a cat. My cat's name is tom.
注意: 所有带有默认值的参数必须放在没有默认值的参数后面,不然程序会报错。
错误示例:
def describe_pet(animal_type='dog',pet_name):
输出:
c:\py>describe_pet.py File "C:\py\describe_pet.py", line 1 def describe_pet(animal_type='dog',pet_name):
把带默认值的参数放最后,这样也可以使用位置实参来传送参数,忽略后面有默认值的形参,剩下的与调用语句中的实参一一对应。
(4) 可选实参
我们可以在定义函数时,把可选参数的默认值设为空,optional argument=''
,这样在调用函数时,即使没有对应的实参,也不会因为实参与形参数量不匹配而报错。
输入:
def get_formatted_name(first_name,last_name,middle_name=''): #给middle_name赋值为空 '''return a full name,neatly formatted.''' 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('jimmi','fallon') print(musician) musician = get_formatted_name('jimmi','fallon','lee') #lee放最后,与middle_name相对应print(musician)
输出:
c:\py>get_formatted_name2 Jimmi Fallon Jimmi Lee Fallon
注意: 上例中的middle_name的默认值为空字符串,因为有默认值,要把它放到最后。Python认为空字符串的值为0,所以if检测到空字符串,即if=0,条件不成立,if下面缩进的语句不执行,转而执行else下面缩进的语句。
4.返回值
Python可以返回任意类型的值。
(1) 返回简单值
我们调用函数后,在函数末尾使用return
语句,可以返回被调用的函数中需要的值;在主程序中,可以使用一个赋值语句接收返回值。
输入:
def get_formatted_name(first_name,last_name): '''return a full name, neatly formatted.''' full_name = first_name+' '+last_name return full_name.title() musician = get_formatted_name('jimmy','logan') #用musician来接收返回值print(musician)
输出:
c:\py>get_formatted_name.pyJimmy Logan
(2) 返回字典
输入:
def get_formatted_name(first_name,last_name): '''return a dictionary of information about a person.''' person={'first':first_name , 'last':last_name} return person musician = get_formatted_name('jimmy','logan') print(musician)
输出:
c:\py>get_formatted_name.py {'first': 'jimmy', 'last': 'logan'}
5.处理列表
(1) 传递列表
可以将一部分列表处理流程分离出来,作为函数,此时,函数中的形参应该是一个列表,在函数中,也作为一个列表进行处理。在主程序中,传送的实参也必须是一个列表。
输入:
def greet_users(names): '''Print a simple greeting to each user in the list.''' for name in names: msg = 'hello, '+name.title()+'!' print(msg) usernames=['jack','tom','lucy'] greet_users(usernames)
输出:
c:\py>greet_users hello, Jack! hello, Tom! hello, Lucy!
(2) 调整列表
调用函数处理列表,给列表带来的变化是永久的。
没有使用函数的程序:
#Start with some designs that need to be printed.unprinted_designs = ['iphone case' , 'robot pendant' , 'dodecahedron'] completed_models = []#Simulate printing each design, until none are left.#Move each design to completed_models after printing.while unprinted_designs: current_design=unprinted_designs.pop() #Simulate creating a 3D print from the design. print('printing model: '+current_design) completed_models.append(current_design)#Display all completed models.print("\nThe following models have been printed : ")for completed_model in completed_models: print(completed_model)
输出:
c:\py>print_model printing model: dodecahedron printing model: robot pendant printing model: iphone caseThe following models have been printed : dodecahedron robot pendant iphone case
我们可以把print_models
和show_completed_models
作为两个函数封装起来。
使用函数的程序:
def print_models(unprinted_designs,completed_models):#Simulate printing each design, until none are left.#Move each design to completed_models after printing. while unprinted_designs: current_design=unprinted_designs.pop() #Simulate creating a 3D print from the design. print('printing model: '+current_design) completed_models.append(current_design)def show_completed_models(completed_models):#Display all completed models. print("\nThe following models have been printed : ") for completed_model in completed_models: print(completed_model) #Start with some designs that need to be printed.unprinted_designs = ['iphone case' , 'robot pendant' , 'dodecahedron'] completed_models = [] print("\nunprinted_designs : "+str(unprinted_designs)+'\n') print_models(unprinted_designs,completed_models) show_completed_models(completed_models) print("\ncompleted_models : "+str(completed_models))
输出:
c:\py>print_model unprinted_designs : ['iphone case', 'robot pendant', 'dodecahedron'] printing model: dodecahedron printing model: robot pendant printing model: iphone caseThe following models have been printed : dodecahedron robot pendant iphone casecompleted_models : ['dodecahedron', 'robot pendant', 'iphone case']
注意: 调用函数处理列表,给列表带来的变化是永久的,就算函数里的形参列表名与主程序中的实参列表名不一致,实参列表依然与形参列表同步变化。
(3) 用切片使函数不改变列表
function_name(list_name[:])
list_name[:]
将列表复制一份,作为参数传给函数,所有的操作只会改变切片,不会改变列表本身。
上例中如果我们不想改变unprinted_designs[:]
列表,我们可以用下面的语句来调用函数。
print_models(unprinted_designs[:],completed_models)
6.特殊的传参情况
(1) 传递任意数量参数
def function_name( *parameters )
在定义函数时,给形参名字前面加上一个‘ * ’号,这时,python会建立一个与形参名同名的元组,将调用函数时传过来的实参,统统保存到元组中。
输入:
def make_pizza(*toppings): '''print the list of toppings that have been requested.''' print(toppings) make_pizza('pepperoni') make_pizza('mushrooms','green peppers','extra cheese')
输出:
c:\py>make_pizza ('pepperoni',) ('mushrooms', 'green peppers', 'extra cheese')
(2) 同时传送位置实参与任意数量实参
和带默认值的形参一样,接收任意数量实参的参数放在位置参数后面。
输入:
def make_pizza(size,*toppings): '''summarize the pizza we are about to make.''' 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')
输出:
c:\py>make_pizza making a 16-inch pizza with the following toppings - pepperoni making a 12-inch pizza with the following toppings - mushrooms - green peppers - extra cheese
(3) 同时传送位置实参和任意数量关键字实参
只在传送不定数量的关键字实参时使用。
def function_name( **parameters )
在定义函数时,给形参名字前面加上一个‘ ** ’号,这时,python会建立一个与形参名同名的字典,将调用函数时传过来的实参nam-value对,以name作为键,以value作为值,保存到字典中。
用“ ** ”表示任意数量关键字参数,并将任意数量关键字实参放在最后。
输入:
def build_profile(first,last,**user_info): '''build a dictionary containing everything we know about a user.''' profile = {} profile['first_name'] = first profile['last_name'] = last for key,value in user_info.items(): profile[key] = value return profile user_profile = build_profile('albert','einstein', location='princeton', field='physics') print(user_profile)
输出:
c:\py>build_profile {'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}
7.while语句和函数
输入:
def get_formatted_name(first_name,last_name): '''return full name''' person=first_name+' '+last_name return personwhile True: print('\nplease tell me your name:') print("(enter 'q' to quit)") f_name=input('First_name : ') if f_name == 'q': #输入q退出程序 break l_name=input('Last_name : ') if l_name == 'q': break formatted_name = get_formatted_name(f_name,l_name) print("Full_name : "+formatted_name)
输出:
c:\py>get_formatted_name please tell me your name: (enter 'q' to quit) First_name : jimmy Last_name : logan Full_name : jimmy logan please tell me your name: (enter 'q' to quit) First_name : tao Last_name : ming Full_name : tao ming please tell me your name: (enter 'q' to quit) First_name :
使用while,我们可以循环调用函数。
8.模块
将函数存储在不同的文件中,可以让我们忽略程序执行的一些细节,只关注更高的逻辑。
原程序:
def make_pizza(size,*toppings): '''summarize the pizza we are about to make.''' 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')
将函数make_pizza作为模块独立出来。
如下:
def make_pizza(size,*toppings): '''summarize the pizza we are about to make.''' print('\nmaking a '+str(size)+'-inch pizza with the following toppings') for topping in toppings: print('- '+topping)
将主程序文件和模块文件放在同一个目录下。
(1) 用import导入整个模块
格式: import module_name
主程序:
import pizza #导入整个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
import pizza
语句会让Python将pizza模块中所有代码复制到主程序开头,使主程序可以使用pizza模块中,所有的函数。
注意: 直接导入整个模块,调用pizza模块中的函数时,需要用一个‘ . ’将模块名和函数名间隔开,格式如下:
module_name.function_name()
(2)导入特定的函数
格式:from module_name import function_name
此时调用函数时不需要‘ . ’来隔开模块名与函数名。
输入:
from pizza import make_pizza #只导入pizza模块中的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
输出与上面的例子相同。
注意: 由于此时只导入特定的函数,所以主程序调用时,不加‘.’号来表示模块中的某个函数。
(3) 使用as给函数起别名
如果导入的函数的名字与主程序中的函数名冲突,又或者导入的函数名太长,我们可以用关键字as
给函数起个别名,主程序可以用别名调用函数。
格式:from module_name import function_name as alias
输入:
from pizza import make_pizza as mp #给make_pizza函数起别名为mpmp(16,'pepperoni') #使用mp调用函数mp(12,'mushrooms','green peppers','extra cheese')
其输出与上例相同。
(4) 使用as给模块起别名
格式:import module_name as alias
输入:
import pizza as p #给pizza模块起别名为pp.make_pizza(16,'pepperoni') #使用mp调用函数p.make_pizza(12,'mushrooms','green peppers','extra cheese')
输出与上例相同。
给模块起简单的别名,可以简化程序,让程序作者将注意力放在描述性强的函数名上。
注意: 这种方法起别名,调用函数时。依然要用‘ . ’将别名与函数名分开。
(5) 导入模块中所有的函数(不推荐)
格式:from pizza imporet *
输入:
from pizza import * #导入所有pizza模块中的函数make_pizza(16,'pepperoni') make_pizza(12,'mushrooms','green peppers','extra cheese')
输出与上例相同。
导入模块中所有的函数后,我们调用函数,就不需要写模块名和‘ . ’,直接使用函数名,但是,如果模块中有和主程序函数名冲突的,往往会造成不可预料的错误。所以不推荐这种导入方法。
9.函数编写风格
(1) 函数的参数赋值,‘=’号两边不留空格
默认值: def function_name(parameter_0,parameter_1='default value')
关键字实参: function_name(value_0,parameter_1='value_1')
(2) 参数字符超过79个
当参数过多时,我们可以将参数拆成多行。
格式:
def function_name( parameter_0,parameter_1,parameter_2, #前面两个tab parameter_3,parameter_4,parameter_5): #前面两个tab function body #前面一个tab
作者:陶不渊
链接:https://www.jianshu.com/p/46e867cafe4d
共同学习,写下你的评论
评论加载中...
作者其他优质文章