定义函数
def greet_user(): """显示简单的问候语""" print("Hello!") greet_user()
函数定义:
- 使用关键字
def
来告诉python要定义一个函数。 函数名
为greet_user。- 要注意的是函数名后面的括号
()
必不可少,尽管有时括号内没有参数。 - 定义以冒号
:
结尾。
文档字符串
- 在第二行中的文本称为文档字符串的注释,是用来描述函数是做什么的。
- 文档字符串和注释的区别为:文档字符串用于介绍我们应该怎样使用这个函数;注释用来注解函数的局部实现方式。
函数体
紧跟在
def greet_user():
后面的所有缩进行
构成函数体。在上面这个例子中,函数体只有一条输出语句。
函数调用
- 函数的功能就是执行某种特定的任务,当程序中需要多次执行某一相同的任务时,调用函数就可以避免编写重复的代码。
- 函数调用时,应指定函数名以及圆括号内的各个参数。
在上述的例子中,函数没有参数,故调用时只需
greet_user()
实参和形参
在上面的例子中稍作改进,我们可以指定函数内的一个参数username
:
def greet_user(username): print(f"Hello,{username.title()}") greet_user('sam')
通过修改,在上述 greet_user(username)函数的括号中多了一个参数username,称为形参,它是函数完成工作所需要的信息,在函数调用时,可以让函数接受我们给username的任何值。
第三行为调用函数,将‘sam’传递给了username,'sam'被赋值给username 'sam'称之为实参。
小小练习
1.消息
编写一个名为display_message()的函数,它打印一个句子,指出你在学的是什么。调用这个函数,确认显示的消息正确无误。
def display_message(): print("I am learning Python.") display_message() //运行结果为:I am leaarning Python.
2.喜欢的图书
编写一个名为favorite_book()的函数,其中包含一个名为title的形参。这个函数打印一条消息。
def favorite_book(title): print(f"My favorite book is {title.title()}") favorite_book('alice') //运行结果为:My favorite book is Alice.
传递实参
函数定义中可能包含多个形参,所以函数调用时也需要向函数传递多个实参,向函数传递实参的方式有很多种,下来一一介绍。
位置实参
将形参与实参关联在一起的最简单的方式就是基于实参位置的一一对应。
接下来举例,来看一个显示宠物信息的函数。这个函数的任务是指出这个宠物属于哪种动物,以及宠物的名字。所以定义这个函数需要两个参数,一个是宠物的类型,一个是宠物的名字。
def discribe_pet(pet_type,pet_name): """显示宠物的信息""" print(f"I have a {pet_type}.") print(f"My {pet_type}'s name is {pet_name}.") discribe_pet('dog','honey')
运行结果为:
I have a dog. My dog's name is honey.
上述例子中函数调用时实参与形参的关联方式就是位置实参
。
所以要使用这种关联方式时,一定要确保实参中参数的顺序正确。
关键字实参
关键字实参
是传递给函数的名称值对
,这样在是实参中就把名称和值关联起来,所以不会产生混淆。关键字实参就不用考虑函数调用时实参的顺序问题了。
以上述函数为例:
discribe_pet(pet_type='dog',pet_name='honey') discribe_pet(pet_name='honey',pet_type='dog')
这两种函数调用方式是等价的。
默认值
编写函数时,可给每个形参指定默认值
。在调用函数时,调用函数中给形参提供了实参时,Python将使用指定的实参值;若调用函数没有给形参提供形参值时,那么将使用形参的默认值。
使用默认值时,最好是现在形参表列中列出没有默认值的形参,然后再列出有默认值的形参。这可以让Python依然能够正确地解读位置实参。
def discribe_pet(pet_name,pet_type='dog'): """显示宠物的信息""" print(f"I have a {pet_type}.") print(f"My {pet_type}'s name is {pet_name}.") discribe_pet('honey') //此时实参可以只有一个
小小练习
1.T恤
编写一个名为make_shirt()的函数,它接受一个尺码以及要印到T恤上的字样。这个函数应打印一个句子,概要地说明T恤的尺码和字样。
def make_shirt(shirt_size,shirt_pattern): print(f"The shirt's size is {shirt_size}and the shirt's pattern is '{shirt_pattern}''.") make_shirt('M','well-being')#位置实参 make_shirt(shirt_size='M',shirt_pattern='well-being')#关键字实参 make_shirt(shirt_pattern='well-being',shirt_size='M')#关键字实参
上面三种是等效的函数调用。
2.大号T恤
修改函数make_shirt(),使其在默认情况
下制作一件印有“I love Python”字样
的大号
T恤。调用这个函数来制作:一件印有默认字样的大号T恤,一件印有默认字样的中号T恤,以及一件印有其他字样的T恤(尺码无关紧要)。
def make_shirt(shirt_size='L',shirt_pattern='I love python'): print(f"The shirt's size is {shirt_size} and the shirt's pattern is 'I love pytthon'.") make_shirt() make_shirt(shirt_size='M') make_shirt(shirt_pattern='I love C')
3.城市
编写一个名为describe_city()的函数,它接受一座城市的名字以及该城市所属的国家。这个函数应打印一个简单的句子。
给用于存储国家的形参指定默认值。为三座不同的城市调用这个函数,且其中至少有一座城市不属于默认国家。
def describe_city(city,country='China'): print(f"{city.title()} is in {country.title()}") describe_city('bejing') describe_city('Shanghai') describe_city('America','New York')
返回值
返回简单值
函数并非总是直接显示输出,它还可以处理一些数据,返回一个或者一组值。函数返回的值称为返回值
,在函数中可以使用return语句
将值返回到调用函数的代码行。
def get_formatted_name(first_name,last_name): """返回整洁的姓名""" full_name=f"{first_name.title()} {last_name.title()}" return full_name musician=get_formatted_name('jimi','hendrix') print(musician)
在上述的函数中,它接受简单的姓和名,并返回整洁的姓名。返回的姓名
即为返回值
。
返回字典
函数可以返回任何类型的值,包括列表和字典等较为复杂的数据结构。
def build_person(first_name,last_name,age=None): """返回一个字典,其中包含有关一个人的信息。""" person={'first':first_name,'last':last_name} if age: person['age']=age return person musician=build_person('jimi','hendrix',age=27) print(musician)
在函数定义中,对于形参age,将其默认值设置为特殊值None
(表示变量没有值),可将None视为占位值。
如果函数调用中包含age的值,那么这个值将被存储到字典中。
结合函数和while循环
利用函数以更正式的方式问候用户。
def get_formatted_name(first_name,last_name): full_name=f"{first_name} {last_name}" return full_name while True: print("Please tell me your name:") print("(enter 'q' at any time to quit)") first_name=input("First name:") if first_name=='q': break last_name=input("Last name:") if last_name=='q': break full_name=get_formatted_name(first_name,last_name) print(f"Hello,{full_name.title()}!")
利用while循环要注意退出条件,不要构成死循环。
因此,每次提示用户输入时,都应提供退出途径。
小小练习
1.城市名
编写一个名为city_country()的函数,它接受城市的名称及其所属的国家。这个函数应返回一个格式类似于下面的字符串:
"Santiago,Chile"
def city_country(city,country): return f"{city.title()},{country.title()}" city1=city_country('bejing','china') city2=city_country('new york','america') city3=city_country('tokyo','japan') print(f"{city1}\n{city2}\n{city3}\n")
2.专辑
编写一个名为make_album()的函数,它创建一个描述音乐专辑的字典。这个函数应接受歌手的名字和专辑名,并返回一个包含这两项信息的字典。使用这个函数创建三个表示不同专辑的字典,并打印每个返回的值,以核实字典正确地存储了专辑的信息。
def make_album(singer_name,album_name): album={'singer':singer_name,'album':album_name} return album album1=make_album('Huachenyu','希忘hope') album2=make_album("Linjunjie","重拾_快乐") album3=make_album("Yukewei","Dear Life") print(f"{album1}\n{album2}\n{album3}\n")
给函数make_album()添加一个默认值为None的可选形参,以便存储专辑包含的歌曲数。如果调用这个函数时指定了歌曲数,就将该值添加到表示专辑的字典中。
def make_album(singer_name,album_name,album_number=None): album={'singer':singer_name,'album':album_name} if album_number: album['number']=album_number return album album=make_album('Huachenyu','希忘Hope',11) print(f"{album}")
传递列表
将列表传递给函数后,函数就能直接访问其内容。
下面举一个例子。
假设有一个用户列表,我们要访问用户列表中的每一位用户,那么我们就可以将一个包含名字的列表传递给函数。
def greet_users(names): for name in names: msg=f"Hello,{name.title()}!" print(msg) usernames=['hannah','ty','margot'] greet_users(usernames)
自定义函数greet_users接受的参数是一个包含名字的列表。
在函数中修改列表
将列表传递给函数后,函数就可对其进行修改。需要注意的是,在函数中对这个列表所做的任何修改都是永久性的。
下面来看个例子:
有一家为用户提交的设计制作3D打印模型的公司,需要打印的设计存储在一个列表中,打印后将移到另一个列表中。
基本思路是:
将需要打印的设计存储在一个列表中,然后定义一个空列表,用于存放已经打印好的设计。
在这个过程中,需要打印的设计列表中,每打印一项,应该把这一项删除,并且将此添加到已经打印好的设计列表中。
如果不使用函数的话:
unprinted_designs=['phone case','robot pendant','dodecahedron'] completed_models=[] while unprinted_designs: current_design=unprinted_designs.pop() print(f"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(unprinted_models,completed_models): while unprinted_models: current_model=unprinted_models.pop() completed_models.append(current_model) def show_completed_models(completed_models): print("\nThe following models have been printed:") for completed_model in completed_models : print(completed_model) unprinted_designs=['phone case','robot pendant','dodecahedron'] completed_models=[] print_models(unprinted_designs,completed_models) show_completed_models(completed_models)
禁止修改函数列表
有时候,需要禁止函数修改函数列表。以上述为例,有一个未打印的列表和一个需要打印的列表,但是有时候有可能在打印出所有需要打印的设计之后,我们仍让需要原来的那个需要的打印的打印,用来备份。
为了解决这个问题,可向函数传递列表的副本,而非原件。
即:
unprinted_designs[:]
小小练习
1.消息
创建一个列表,其中包含一系列简短的文本消息。将该列表传递给一个名为show_messages()的函数,这个函数会打印列表中的每条文本消息。
def show_messages(messages): for message in messages: print(message) messages=['Hi','Nice to meet you','ET','!'] show_messages(messages)
2.发送消息
编写一个名为send_messages()的函数,将每条消息都打印出来并移到一个名为sent_messages的列表中。调用函数send_messages(),再将两个列表都打印出来,确认正确地移动了消息。
def send_messages(send_messages,sent_messages): for send_message in send_messages: print(send_message) while send_messages: current_message=send_messages.pop() sent_messages.append(current_message) send_messages_=['A','B','C','D'] sent_messages_=[] send_messages(send_messages_,sent_messages_) for send_message in send_messages_: print(send_message) for sent_message in sent_messages_: print(sent_message)
3.消息归档
在练习2的基础上,在调用函数send_messages()时,向它传递消息列表的副本。调用函数send_messages()后,将两个列表都打印出来,确认保留了原始列表中的消息。
def send_messages(send_messages,sent_messages): for send_message in send_messages: print(send_message) while send_messages: current_message=send_messages.pop() sent_messages.append(current_message) send_messages_=['A','B','C','D'] sent_messages_=[] send_messages(send_messages_[:],sent_messages_) #传递副本 for send_message in send_messages_: print(send_message) for sent_message in sent_messages_: print(sent_message)