函数
1. 定义函数
def greet_user():
"""显示简单的问候语"""
print("你好!")
greet_user()
-----------------------------------------------------------------------------------
结果:
你好!
这是一个简单的函数,在此例中:
第一行为函数名,代表我要创建的是一个函数;
第二行为文档字符串的注释,描述了此函数是用来做什么的;
第三行为函数体内需要执行的代码;
最后一行为调用此函数。
2. 向函数传递信息
def greet_user(username):
"""显示简单的问候语"""
print(f"你好!{username.title()}")
greet_user("zhangsan")
-----------------------------------------------------------------------------------
结果:
你好!Zhangsan
在此例中,给函数加入了参数,并写在了函数体内,这样有人需要使用这个函数都必须给一个参数,这边这个参数为使用者的名字,输入名字后就会向你问好。
在上面的实验中,函数定义的变量username是一个形参,在调用次函数时传入的是实参;
3. 传递实参 — 位置实参
调用函数是,必须将函数调用中的每个实参都关联到函数定义中的一个形参,最简单的关联方式是基于实参的顺序,这种关联方式称为位置实参。
# 定义函数,参数为宠物类型和名字
def my_pet(pet_type, pet_name):
"""显示最喜欢的宠物以及名字"""
print(f"我最喜欢的动物是{pet_type}")
print(f"它的名字叫:{pet_name}")
# 调用函数的时候需要传入宠物的类型和名字
my_pet("小狗", "皮皮")
-----------------------------------------------------------------------------------
结果:
我最喜欢的动物是小狗
它的名字叫:皮皮
4. 传递实参 — 关键字实参
关键字实参是传递给函数的名称值对,因为直接在实参中将名称和值关联起来了,所以向函数传递实参是不会混淆,关键字实参可以无须考虑函数调用的实参顺序。
# 定义函数,参数为宠物类型和名字
def my_pet(pet_type, pet_name):
"""显示最喜欢的宠物以及名字"""
print(f"我最喜欢的动物是{pet_type}")
print(f"它的名字叫:{pet_name}")
# 调用函数的时候需要传入宠物的类型和名字,使用了关键字调用
my_pet(pet_name="皮皮", pet_type="小狗")
-----------------------------------------------------------------------------------
结果:
我最喜欢的动物是小狗
它的名字叫:皮皮
5. 传递实参 — 默认值
1.编写函数时,可以给每个形参指定默认值,这样在调用的时候,如果没有提供实参,将使用默认值。
2.这个函数中,不仅给一个形参添加了默认值,还修改了形参的顺序,因为pet_type指定了默认值,无需通过实参来指定,所以在函数调用中只有一个实参pet_name,所以可以理解为这是一个位置实参。
def my_pet(pet_name, pet_type='小狗'):
"""显示最喜欢的宠物以及名字"""
print(f"我最喜欢的动物是{pet_type}")
print(f"它的名字叫:{pet_name}")
# 调用函数的时候需要传入宠物的类型和名字,使用了关键字调用
my_pet(pet_name="皮皮")
-----------------------------------------------------------------------------------
结果:
我最喜欢的动物是小狗
它的名字叫:皮皮
6. 返回简单值
函数并非总是直接显示输出,它还可以处理一些数据,并返回一个或一组值。函数返回的值称为返回值,在函数中,可使用return语句将值返回到调用函数的代码行,返回值让你能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序
def get_formatted_name(first_name, last_name):
"""返回整洁的名字"""
full_name = f"{first_name} {last_name}"
#返回完成的名字,并将首字母大写
return full_name.title()
#定义一个变量用于接受传入了参数的函数结果
musician = get_formatted_name('zhang', 'san')
print(musician)
-----------------------------------------------------------------------------------
结果:
Zhang San
有时候们需要让实参变成可选的,这样使用函数的人就能只在必要的时候提供额外的信息,可以使用默认值来让实参变成可选的。
#定义一个函数,中间值默认为空,因为不是所有人都有中间名,如果有三个形参,但是只传入两个实参则会报错
def get_formatted_name(first_name, last_name, middle_name=''):
"""返回整洁的名字并做判断,如果有中间名则返回传入的实参"""
if middle_name:
full_name = f"{first_name} {middle_name} {last_name}"
#如果没有中间名则返回默认值
else:
full_name = f"{first_name} {last_name}"
return full_name.title()
#使用没有中间字的姓名来测试
musician = get_formatted_name('zhang', 'san')
print(musician)
#使用包含中间字的姓名来测试
musician2 = get_formatted_name('sun', 'wu', 'kong')
print(musician2)
-------------------------------------------------------------------------------
结果:
Zhang San
Sun Kong Wu
7.返回字典
函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。例如下面的函数接受姓名的组成部分,并返回一个表示姓名的字典
#定义一个函数,形参包括firs_name和last_name
def build_name(first_name, last_name):
#定义字典person,添加键为first和last,值为函数的实参
person = {'firs': first_name, 'last': last_name}
return person
#传入姓名进行测试
musician = build_name("zhang", "san")
print(musician)
-----------------------------------------------------------------------------------
结果:
{'firs': 'zhang', 'last': 'san'}
在函数定义中,新增一个可选形参age,并将其默认值设置为特殊值None(表示变量没有值)。可将None视为占位值,在测试中,如果函数调用中包含形参age的值,那么这个值将会被存储在字典中。
#定义一个函数,形参包括firs_name、last_name和默认值为None的age
def build_name(first_name, last_name, age=None):
#定义字典person,添加键为first和last,值为函数的实参
person = {'firs': first_name, 'last': last_name}
#判断调用函数的传入的实参是否有age,有的话则添加到字典里面,age作为键,实参作为值
if age:
person['age'] = age
return person
#不包含age的实参做测试
musician = build_name("li", "si")
print(musician)
#包含age的实参做测试
musician = build_name("zhang", "san", age=18)
print(musician)
-----------------------------------------------------------------------------------
结果:
{'firs': 'li', 'last': 'si'}
{'firs': 'zhang', 'last': 'san', 'age': 18}
8.结合使用函数和while循环
使用while循环存在一个问题:没有定义退出条件,要想解决这个问题,我们需要添加一条消息来告诉用户如何退出,如果符合,那就退出循环,如果不符合将一直进行循环,如下例:
#定义一个函数为得到完整的姓名,参数包括第一个字,和最后一个字,这里不包括中间字
def get_formatted_name(first_name, last_name):
"""返回整洁的姓名"""
full_name = f"{first_name} {last_name}"
#将得到的姓名首字母大写
return full_name.title()
#这里是一个死循环
while True:
print("请告诉我你的名字")
print("按q可以退出")
#如果用户在输入名字的第一个字的时候输入了q,name程序将结束
f_name = input("first_name:")
if f_name == "q":
break
#如果用户在输入名字的最后一个字的时候输入了q,name程序将结束
l_name = input("last_name")
if l_name == "q":
break
#调用函数,将用户输入的参数作为实参传入函数中
formatted_name = get_formatted_name(f_name, l_name)
print(f"\nHello!{formatted_name}")
----------------------------------------------------------------------------------
结果:
请告诉我你的名字
按q可以退出
first_name:hello
last_namekitty
Hello!Hello Kitty
请告诉我你的名字
按q可以退出
first_name:q
进程已结束,退出代码为 0
9.传递列表
我们可以发现,向函数传递列表很有用,其中包含的可能是名字、数字或者更复杂的对象(比如字典),将列表传递给函数后,函数就能直接访问其内容,下面演示使用函数来提高处理列表的效率。
#定义欢迎用户的函数,形参为names
def greet_users(names):
#对传入的参数进行for循环
for name in names:
#编写欢迎语句,将用户的首字母进行大写
msg = f"Hello,{name.title()}"
print(msg)
#定义一个列表的内容
usernames = ['zhangsan', 'lisi', 'wangwu']
#调用上面的函数,传入的实参为上面的列表
greet_users(usernames)
----------------------------------------------------------------------------------
结果:
Hello,Zhangsan
Hello,Lisi
Hello,Wangwu
10.在函数中修改列表
将列表传递给函数后,函数就可以对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,这可以让你能能够高效的处理大量数据。
案例:模型打印店制作模型,需要打印的设置存在一个列表中,打印后移到另一个列表中。
#定义没有制作的模型列表
unprinted_designs = ['手机模型', '电视机模型', '电脑模型']
#定义已经制作的模型列表,一开始为空
completed_models = []
#使用while循环没有制作的模型列表
while unprinted_designs:
#定义变量当前制作的模型为模型列表中移出的数据(末尾)
current_design = unprinted_designs.pop()
print(f"正在制作::{current_design}")
#将未制作模型列表移除的数据,加入到已制作模型列表的列表当中
completed_models.append(current_design)
print(f"以下的模型是制作完成的:")
#使用for循环将以及制作完成的模型进行遍历打印出来
for completed_model in completed_models:
print(completed_model)
----------------------------------------------------------------------------------
结果:
正在制作::电脑模型
正在制作::电视机模型
正在制作::手机模型
以下的模型是制作完成的:
电脑模型
电视机模型
手机模型
重新组织上例中的这些代码,可编写两个函数,每个都做一件具体的工作,大部分代码与原来相同,知识效率更高,第一个函数负责处理打印设计的工作,第二个函数负责概述打印了哪些设计。
#第一个函数负责处理打印设计的工作
def make_models(unprinted_designs, completed_models):
while unprinted_designs:
current_design = unprinted_designs.pop()
print(f"正在制作::{current_design}")
completed_models.append(current_design)
#第二个函数负责概述打印了哪些设计
def show_models(completed_models):
for completed_model in completed_models:
print(completed_model)
##定义没有制作的模型列表
unprinted_designs = ['手机模型', '电视机模型', '电脑模型']
#定义已经制作的模型列表,一开始为空
completed_models = []
#调用上面两个函数,分别将我们定义的列表作为实参传入到函数中
make_models(unprinted_designs, completed_models)
show_models(completed_models)
----------------------------------------------------------------------------------
结果:
正在制作::电脑模型
正在制作::电视机模型
正在制作::手机模型
电脑模型
电视机模型
手机模型
相比没有使用函数的版本,这个程序更容易扩展和维护,如果以后需要打印其他设计,只需要再次调用函数make_models()
即可,如果发现旭泰对打印代码进行修改,只需要修改这些代码一次,就能够影响所有调用该函数的地方,与必须分别修改程序的多个地方相比,这种修改的效率更高。