在这一章你将学习如何将函数存储在称为模块的独立文件中
1.定义函数
def greet_user(username):
"""显示简单的问候语"""#文档字符串的注释,描述了函数是做什么的
print("hello!")
def greet_user(username):
"""简单的问候语"""
print("Hello, "+username.title()+"!")
greet_user('helly')
其中三个引号引用的是文档字符串的注释,描述了函数是做什么的
1.1向函数传递参数
我们在写函数的时候可以在()内写上我们需要的参数并且在函数内部应用它,比如上述greet_user()代码的内部的username,就在内部进行了调用。
1.2 实参和形参
在上述代码中username是一个----形参,而用户传给函数的参数是helly是一个实参,在函数中进行了将实参helly传给形参username(所以在程序中一定要认清谁是形参谁是实参)
2传递实参
在函数的定义中可能存在多个形参,因此在函数调用的时候存在多个实参,向函数传递实参的方法有很多有----位置实参,这要求实参的顺序与形参的顺序相同:当然也可以使用关键字实参,其中每个实参都是由变量名和值组成:还可以使用列表和字典
2.1位置实参
def describe_pet(animal_type,pet_name):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet('hamster','harry')
在上述代码中就直接把hamster赋给animal_type,把harry赋给pet_name
输出为一只名为Harry的仓鼠
这种位置实参的方法就需要你的参数位置和你在函数中定义的位置严格符合,如果你在上诉程序中将仓鼠和harry交换了位置那么就会输出一只名为仓鼠的harry。
2.2关键字实参
def describe_pet(animal_type,pet_name):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet(animal_type='hamster',pet_name='harry')#关键字实参的顺序无关紧要
关键字实参传递的是名称-值对,你直接子啊实参中将名称和值关联起来,因此在向函数传递的时候就不会混淆
2.3在参数中添加默认值
在编写函数的时候,可以给函数中的参数添加默认值,若在用户调用中没有为这些参数赋值那就是用默认值
def describe_pet(pet_name,animal_type='dog'):#提前设定一个默认值放在后面
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet(pet_name='willie')
在使用默认值的时候,在形参列表中必须向列出没有默认值的形参,在列出有默认值的实参,让python能够正确的解读位置实参
2.4避免实参错误
在我们使用参数后可能会遇到参数不匹配的错误,这时候编译器的traceback会为我们指出函数内部缺失参数的提示
3返回值
函数也并非总是直接显示输出,他可以处理一些数据,并返回一个或者一组值,函数返回的值称为返回值,在函数中是使用return来返回一个值
3.1返回简单值
下面一个函数,它接受名和姓并返回整洁的姓名
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)
3.2让实参变成可选的
有时候需要让实参变成可选的,这样使用参数的人就秩序在必要的时才提供额外的信息。可以使用默认值来让实参变成可选的,正如下面这个程序
#让实参变成可选的
#这样使用函数的人在必要时才提供额外的信息,可以用默认值让实参变成可选的
def get_formatted_name(first_name,middle_name,last_name):
full_name = first_name+' '+middle_name+' '+last_name
return full_name.title()
musician=get_formatted_name('john','lee','hooker')
print(musician)
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()
在这就可以让middle_name成为一个可选择的实参,但是要注意要将其移到形参列表的末尾
3.3返回字典
函数可以返回任意类型的值,包括字典和列表,下面这个程序接受姓名的组成部分,并返回一个表示人的字典
#返回字典
#函数可以返回任何类型的值
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',age=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("\nEnter 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+"!")
4.传递列表
向函数传递列表很有用,这种列表可能包含名字,数字或是更复杂的对象,将列表传递给函数后,函数就能直接访问其内容。下面使用函数来提高处理列表的效率
#传递列表
#用函数来提高处理列表的效率
def greet_user(names):
"""向列表的每位用户发出简单的问候"""
for name in names:
msg ="Hello, "+name.title()+"!"
print(msg)
usernames =['ls','baobao','beibei']
greet_user((usernames))
向参数中传递了一个名字的列表,然后循环读取
4.1 在函数中修改列表
将列表传给函数后,函数就可以对它进行修改,在函数中对这个列表所做的任何修改都是永久性的,这让你能够高效的处理大量的数据
#在函数中修改列表
#将列表传递给函数后函数可以对列表进行修改
#首先创建一个列表,其中包含一些打印设计
unprinted_designs=['iphone case','robot pendant','dpdecahedrom']
completed_models=[]
#模拟打印每一个设计,知道没有未打印为止
#打印每个设计后,都将其移到列表completed_models中
while unprinted_designs:
current_design = unprinted_designs.pop()
#模拟根据设计制作模型的过程
print("Printing mode: "+current_design)
completed_models.append(current_design)
#显示打印好的模型
print("\nThe following models have been prnted:")
for completed_model in completed_models:
print(completed_model)
当然 我们可以对这个函数进行重构,把其改写为两个函数
def print_models(unprinted_designs,completed_models):
while unprinted_designs:
current_design = unprinted_designs.pop()
#模拟根据设计制作模型的过程
print("Printing mode: "+current_design)
completed_models.append(current_design)
def show_completed_models(completed_models):
print("\nThe following models have been prnted:")
for completed_model in completed_models:
print(completed_model)
unprinted_designs=['iphone case','robot pendant','dpdecahedrom']
completed_models=[]
print_models(unprinted_designs,completed_models)
show_completed_models(completed_models)
每个函数都只负责一项具体的工作,第一个函数打印的每个设计,第二个显示打印好的模型:这优于使用一个函数来完成两项工作。编写函数时,同样可以这样,把不同功能的代码段,分成两个函数。
4.2禁止函数修改列表
有时候需要禁止函数修改列表,比如上述你需要保存打印模型的列表但是上述的程序执行完后要打印物品的列表就像变成空列表,这时候我们可以给参数传递一个列表的复制值
function_name(list_name[:])
5传递任意数量的实参
#传递任意数量的实参
#有时候你不知道函数接受多少个实参,python允许函数从调用语句中任意数量的实参
#不管调用语句提供了多少实参,这个形参都将他们统统收入囊中
def make_pizza(*toppings):#*topping这个星号让python创建一个名为toppings的空元组,并将收到的所有值都封装在这个元组上
print(toppings)
make_pizza('p')
make_pizza('m','g','e')
#我们可以把print语句替换成一个循环
# def make_pizza(*toppings):#*topping这个星号让python创建一个名为toppings的空元组,并将收到的所有值都封装在这个元组上
print("\nMaking a pizza with the following toppings: ")
for topping in toppings:
print("-"+topping)
make_pizza('p')
make_pizza('m','g','e')
5.1结合使用位置实参和任意数量实参
可以将函数定义中的接纳任意数量实参的形参放在最后,Python先匹配位置实参和关键字实参,再将余下的实参都受收集到最后的一个形参中。
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',locaton='princeeton',field='physics')
print(user_profile)