时间:2018/04/30
主要内容:函数
函数
定义函数
def greet_user():
'''显示简单的问候语'''
print('Hello!')
greet_user()
#其中第二行的文本被称为‘文档字符串’(docstring)的注释,描述函数是做什么的。文档字符串用三引号括起来,python使用它们来生成有关程序中的文档。
向函数传递信息
def greet_user(username):
'''显示简单的问候语'''
print('Hello ' + username.title() + '!')
greet_user('tom')
实参和形参
比如前面函数greet_user()定义时,变量username为一个形参——函数完成其工作所以需要的一项信息。
在代码greet_user('jesse')中,值'jesse'是一个实参。实参是调用函数时传递给函数的信息。在该代码中将实参'jesse'传递给函数greet_user(),这个值被储存在形参username中。
传递参数
像函数传递实参的方式很多,可以使用位置实参,这要求实参的顺序与形参的顺序相同,也可以使用关键字实参,其中每个实参都由变量名和值组成,还可以使用列表和字典。
位置实参
def describe_pet(animal_type,pet_name):
'''显示宠物的信息'''
print('\nI have a ' + animal_type + '.')
print('My ' + animal_type + '\'s name is ' + pet_name + '.')
describe_pet('hamster','harry')
!注意实参排列顺序要严格和形参的排列顺序相同。
关键字实参
传递给函数的是名称-值对。直接在实参中将名称和值关联起来,因此向函数传递实参时不会混淆。关键字实参可以不用考虑函数调用中的实参顺序,还可以清楚指出函数调用中的各个值的用途。
def describe_pet(animal_type,pet_name):
'''显示宠物的信息'''
print('\nI have a ' + animal_type + '.')
print('My ' + animal_type + '\'s name is ' + pet_name + '.')
describe_pet('hamster','harry')
describe_pet(pet_name = 'willie',animal_type = 'dog')
默认值
编写函数时,可以给每个形参指定默认值。为了避免参数的混乱,一般将带默认值的参数放在最后面。
def describe_pet(pet_name,animal_type='hamster'):
'''显示宠物的信息'''
print('\nI have a ' + animal_type + '.')
print('My ' + animal_type + '\'s name is ' + pet_name + '.')
describe_pet('harry')
该函数中,由于宠物类型给了默认值,无需通过实参来指定动物类型,因此在该函数中只包含一个实参——宠物的名字。但是Pyhton依然将该实参视为位置参数,会将该实参关联到函数定义中的第一个形参。
等效的函数调用
def describe_pet(pet_name,animal_type='hamster'):
'''显示宠物的信息'''
print('\nI have a ' + animal_type + '.')
print('My ' + animal_type + '\'s name is ' + pet_name.title() + '.')
#一只名为Harry的仓鼠
describe_pet('harry')
describe_pet(pet_name = 'harry')
#一条名字时willie的小狗
describe_pet('willie','dog')
describe_pet(pet_name = 'willie',animal_type = 'dog')
describe_pet(animal_type = 'dog',pet_name = 'willie')
避免实参错误
当你提供的实参多于或者少于函数完成其工作所需的信息时,将出现实参不匹配错误。
返回值
函数并非总是显示输出,它可以处理一些数据,并返回一个或者一组值。函数返回的值称为返回值。
返回简单值
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)
#吉米·亨德里克斯(James Marshall "Jimi" Hendrix,1942年11月27日-1970年9月18日),出生于美国华盛顿州西雅图,美国吉他手、歌手、作曲人,被公认为是摇滚音乐史中最伟大的电吉他演奏者。点击打开链接
让实参变成可选的
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)
返回字典
函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。
def build_person(first_name,last_name):
'''返回一个字典,其中包括含有关一个人的信息'''
person = {'first':first_name,'last':last_name}
return person
musician = build_person('jimi','hendrix')
print(musician)
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',27)
print(musician)
结合使用函数和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 + '!')
传递列表
def greet_users(names):
'''向列表中的每位用户都发出简单的问候'''
for name in names:
msg = 'Hello,' + name.title() + '!'
print(msg)
usersnames = ['hannah','ty','margot']
greet_users(usersnames)
在函数中修改列表
打印储存在一个列表中的数据并存储带另一个列表中:不使用函数的代码如下
#首先创建一个列表,里面包括一些要打印的设计
unprinted_designs = ['iphone case','robot pendant','dodecahedron']
completed_models = []
#模拟打印每个设计,直到没有未打印的设计为止
#打印每个设计后,都将其移入已完成列表中
while unprinted_designs:
current_design = unprinted_designs.pop()
#模拟设计打印的过程
print('Printing model: ' + current_design)
completed_models.append(current_design)
#显示已经打印的设计
print('\nThe following models have been printed:')
for completed_model in completed_models:
print(completed_model)
我们设计两个函数来完成以上过程
def print_models(unprint_designs,completed_designs):
'''
模拟打印每个设计,直到没有未打印的设计为止
打印每个设计后,都将其移入completed_desigs列表中
'''
while unprint_designs:
current_design = unprint_designs.pop()
print('Printing design:' + current_design)
completed_designs.append(current_design)
def show_completed_designs(completed_designs):
'''显示打印的设计'''
print('\nThe following models have been printed:')
for completed_design in completed_designs:
print(completed_design)
unprint_designs = ['iphone case','robot pendant','dodecahedron']
completed_designs = []
print_models(unprint_designs,completed_designs)
show_completed_designs(completed_designs)
以上例子也演示了一种理念:一个函数都应该只负责一项具体的工作!
禁止函数修改列表
可以使用切片表示法[:]创建列表副本。从避免浪费时间和内存的角度,如果没有充分的理由需要传递副本,否则还是应该将原始列表传递给函数。
传递任意数量的实参
“*形参”中的星号是让Python创建一个名为形参的空元组并将所有收到的值都储存在这个元组中
def make_pizza(*toppings):
'''概述要制作的披萨'''
print('\nMaking a pizza with the following toppings:')
for topping in toppings:
print('-' + topping)
make_pizza('pepperoni')
make_pizza('pepperoni','mushrooms')
结合使用位置实参和任意数量实参
def make_pizza(size,*toppings):
'''概述要制作的披萨'''
print('\nMaking a pizza ' + str(size) + ' with the following toppings:')
for topping in toppings:
print('-' + topping)
make_pizza(16,'pepperoni')
make_pizza(20,'pepperoni','mushrooms')
使用任意数量的关键字参数
有时候,需要接受任意数量的实参,但预先不知道传递给函数的会是什么信息。这种情况下,可将函数编写成能够接受任意数量的键-值对——调用语句提供多少就接受多少。
def build_profile(first,last,**user_info):
'''创建一个字典,其中包括我们知道的有关用户的一切'''
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)
编写函数时,你可以使用各种方式混合使用位置实参、关键字实参和任意数量的实参。
将函数储存在模块中
函数优点之一是,使用他们可将代码块与主程序分离。也可以更近一步,将函数储存在被称为模块的独立文件中,再将模块导入到主程序中,import语句允许在当前运行的程序文件中使用模块的代码。通过将函数储存在独立文件中,可以隐藏程序代码细节,将重点放在逻辑层面上,也可以使你在不同的程序中重复调用函数。
导入整个模块
现有模块pizza.py
def make_pizza(size,*toppings):
'''概述要制作的披萨'''
print('\nMaking a pizza ' + str(size) + ' with the following toppings:')
for topping in toppings:
print('-' + topping)
在pizza.py所在目录创建另一个项目调用make_pizza():
import pizza
pizza.make_pizza(16,'pepperoni')
pizza.make_pizza(12,'mushrooms','green peppers','extra cheese')
调用被导入模块中的函数,可指定导入的模块的名称pizza和函数名make_pizza(),并用句点分隔他们
module_name.function_name()
导入特定的函数
从模块中导入特定的函数,可以使用以下语法:
from module_name import function_name
#导入任意数量函数,函数名中间用逗号隔开
from module_name import function_0,function_1,function_2
使用这种语法,调用函数时就无需使用句点。
使用as给函数指定别名
from module_name import fuction_name as fn
使用as给模块指定别名
import module_name as mn
导入模块中的所有函数
from module_name import *
谨慎使用该语法,在大型工程中盲目导入所有模块的所有函数可能会遇到多个名称相同的函数或者变量,进而覆盖函数,而不是分别导入所有函数。
函数编写指南
形参指定默认值时等号两端不要有空格
形参较多时,导致自定义函数的长度超过了79字符,可以在函数定义中输入括号后按回车,并在下一行按两次tab,从而将形参列表与只缩进一层的函数体区别开来(前面部分代码虽然没有错误,但是不够规范易读性差,由于懒就先没有修改T T)
程序或者模块包含多个函数时,可以使用两个空行将相邻的函数分开