函数是带名字的代码块
8.1定义函数
使用关键字def 告诉python你要定义一个函数。

def greet_user():#()是必要的
	print("Hello!")
greet_user()
结果:
Hello!
[Finished in 0.1s]

8.1.1向函数传递信息
8.1.2实参和形参

def greet_user(username):#形参
	print(f"Hello,{username.title()}")
greet_user("tachyon xue")#()内是实参
结果:
Hello,Tachyon Xue
[Finished in 0.1s]

练习8-1:消息

def display_message():
	print("本章学习的是函数'def'")
display_message()
结果:
本章学习的是函数'def'
[Finished in 0.1s]

练习8-2:喜欢的图书

def favorite_book(title):
	print(f"我最喜欢的书《{title}》")
favorite_book('爱丽丝梦游仙境')
结果:
我最喜欢的书《爱丽丝梦游仙境》
[Finished in 0.1s]

8.2传递实参
函数定义可包含多个形参,因此函数调用也可包含多个实参。
每个实参都有变量名和值组成,也可以是列表和字典。
8.2.1位置实参
所谓位置实参就是,形参和实参位置要相互对应。

  1. 多次调用函数
def describe_pet(animal_type, pet_name):
	print(f"\nI have a {animal_type}")
	print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('hamster', 'harry')#第一次调用,对应形参位置
describe_pet('dog', 'willie')#第二次调用,对应形参位置
.....
......
....
结果:

I have a hamster
My hamster's name is Harry.

I have a dog
My dog's name is Willie.
[Finished in 0.1s]
  1. 位置实参的顺序很重要
def describe_pet(animal_type, pet_name):
	print(f"\nI have a {animal_type}")
	print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('harry', 'hamster')#如果位置对应错了,程序不会出错但结果就不是你要的结果了。
结果:

I have a harry
My harry's name is Hamster.
[Finished in 0.1s]

8.2.2关键字实参
关键字实参是转递给函数的名称值对,因为直接在实参中将名称和值关联起来,所以向函数传递实参时不会混淆。也无须考虑函数调用中的实参顺序。

def describe_pet(animal_type, pet_name):
	print(f"\nI have a {animal_type}")
	print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('hamster', 'harry') #位置实参
describe_pet(animal_type='hamster', pet_name='harry')#关键字实参
结果:

I have a hamster
My hamster's name is Harry.

I have a hamster
My hamster's name is Harry.
[Finished in 0.1s]

8.2.3默认值
为了简化,我们可以在起初编写函数的时候,给每个形参指定默认值,这样在调用函数的时候就不用在写实参了。
使用默认值,在函数调用时候遵循’位置实参‘
注意:使用默认值,必须先在形参列表中列出没有默认值的形参,再列出有默认值的形参=实参。

def describe_pet(pet_name, animal_type='dog'):  #先写没默认值的形参。
	print(f"\nI have a {animal_type}")
	print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('wille')#这里没有指定位置2个实参,使用了默认值
结果:

I have a dog
My dog's name is Wille.
[Finished in 0.1s]

8.2.4等效的函数调用
位置实参、关键字实参和默认值。可混用。
8.2.5避免实参错误
有多少形参,写多少实参,避免少写或多写
练习8-3:T恤

def make_shirt(size, word):
	print(f"我的衣服是{size}码,上面写着{word}")
make_shirt(75, '我爱祖国')#位置实参调用
make_shirt(size=75, word='我爱祖国')#关键字实参调用
结果:
我的衣服是75码,上面写着我爱祖国
我的衣服是75码,上面写着我爱祖国
[Finished in 0.1s]

练习8-4:大号T恤

def make_shirt(size, word='I love Python'):
	print(f"我的衣服是{size}码,上面写着{word}")
make_shirt('大号')
make_shirt('中号')
make_shirt('小号', '我爱祖国')
结果:
我的衣服是大号码,上面写着I love Python
我的衣服是中号码,上面写着I love Python
我的衣服是小号码,上面写着我爱祖国
[Finished in 0.1s]

练习8-5:城市

def describe_city(city, state='中国'):
	print(f"{city}属于{state}")
describe_city('昆明')
describe_city('太原')
describe_city('拉斯维加斯', '美国')
结果:
昆明属于中国
太原属于中国
拉斯维加斯属于美国
[Finished in 0.1s]

8.3返回值
return语句将值返回到调用函数的代码行中去完成,来简化主程序。
8.3.1返回简单值

def get_formatted_name(first_name, last_name):
	full_name = f"{first_name} {last_name}"
	return full_name.title()#return将值返回给函数调用行
musician = get_formatted_name('tachyon', 'xue')#返回值赋给了一个变量musician
print(musician)
结果:
Tachyon Xue
[Finished in 0.1s]

8.3.2让实参成可选的
我们可以把形参使用默认值,并把默认值设置为空字符串,并使用条件来判断是否使用这个默认值为空的形参。
在python里非空字符串被解释为“True”,空字符串解释为“False”

def get_formatted_name(first_name, last_name, middle_name=''):
	if middle_name:  #条件判断函数的有默认值的形参当为空字符串时为False;当不为空字串时为True。
		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('jimi', 'hendrix')#实参只写了2个第3个使用默认值,则是空,为False
print(musician)
musician = get_formatted_name('john', 'hooker', 'lee')
print(musician)
结果:
Jimi Hendrix
John Lee Hooker
[Finished in 0.1s]

8.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)
结果:
{'first': 'jimi', 'last': 'hendrix'}
[Finished in 0.1s]
def build_person(first_name, last_name, age=None):#None占位值,可看作False.这里用空字符作用一样。
	person = {'first': first_name, 'last': last_name} #将键值对赋给变量
	if age:
		person['age'] = age
	return person
musician = build_person('jimi', 'hendrix', age=22)
print(musician)
结果:
{'first': 'jimi', 'last': 'hendrix', 'age': 22}
[Finished in 0.1s]

8.3.4结合使用函数和while循环

def get_formatted_name(first_name, last_name):
	full_name = f"{first_name} {last_name}"
	return full_name.title()
while True: #while 为True程序为循环中。
	print("\n请告诉我你的名字")
	print("输入小写字母'q'键可随时退出程序。")
	f_name = input("你叫什么名字:")
	if f_name == 'q':  #条件判断退出程序。
		break
	l_name = input("你姓什么:")
	if l_name == 'q':
		break
	formatted_name = get_formatted_name(f_name, l_name)
	print(f"\n你好,{formatted_name}")

练习8-6:城市名

def city_country(city, country):
	city_country_0 = f"{city}, {country}"
	return city_country_0.title()
attach_to = city_country('西安', '中国')
print(attach_to)
attach_to = city_country('tokyo', 'japanese')
print(attach_to)
attach_to = city_country('pattaya', 'thailand')
print(attach_to)
结果:
西安, 中国
Tokyo, Japanese
Pattaya, Thailand
[Finished in 0.1s]

练习8-7:专辑

def make_album(singer_name, album_name, number_song=None):
	albums = {
		'singer': singer_name,
		'album': album_name
		}
	if number_song:
		albums['number_song'] = number_song
	return albums#一定要注意return的缩进,它不是if的缩进,而是def函数的缩进。
singers = make_album('刘德华', '忘情水')
print(singers)
singers = make_album('张学友', '吻别')
print(singers)
singers = make_album('陈奕迅', '十年', number_song=12)
print(singers)
结果:
{'singer': '刘德华', 'album': '忘情水'}
{'singer': '张学友', 'album': '吻别'}
{'singer': '陈奕迅', 'album': '十年', 'number_song': 12}
[Finished in 0.1s]

练习8-8:用户专辑

def make_album(singer_name, album_name, number_song=None):
	albums = {
		'singer': singer_name,
		'album': album_name
		}
	if number_song:
		albums['number_song'] = number_song
	return albums#一定要注意return的缩进,它不是if的缩进,而是def函数的缩进。
singers = make_album('刘德华', '忘情水')
print(singers)
singers = make_album('张学友', '吻别')
print(singers)
singers = make_album('陈奕迅', '十年', number_song=12)
print(singers)
print("\n你还知道哪些专辑和歌手")
while True:
	print("写出你知道的歌手名字和专辑名字:")
	print("当输入小写字母'q'可以随时退出")
	s_name = input("歌手名字:")
	if s_name == 'q':
		break
	a_name = input("专辑名字:")
	if a_name == 'q':
		break
	albums = make_album(s_name, a_name)
	print(albums)

8.4传递列表

def greet_users(names):#names形参
	for name in names:
		msg = f"Hello, {name.title()}"
		print(msg)
usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)#usernames实参
结果:
Hello, Hannah
Hello, Ty
Hello, Margot
[Finished in 0.1s]

8.4.1在函数中修改列表
对比两段代码,不使用函数和使用函数。
不使用函数:

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)
结果:
Printing model:dodecahedron
Printing model:robot pendant
Printing model:phone case

The following models have been printed:
dodecahedron
robot pendant
phone case
[Finished in 0.1s]

下面是使用了函数的:

#第一个函数,打印列表和打印好的列表
def print_models(unprinted_designs, completed_models):
	while unprinted_designs:
		current_design = unprinted_designs.pop()
		print(f"Printing model:{current_design}")
		completed_models.append(current_design)
#第二个函数,显示出打印好的列表中的每个模型
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)
结果:
Printing model: dodecahedron
Printing model: robot pendant
Printing model: phone case

The following models have been printed:
dodecahedron
robot pendant
phone case
[Finished in 0.1s]

学习到这对python函数中的return的使用有点迷,查了查资料,现在简单记录下:

作用是函数执行结果返回给调用程序,可用来保存进行再计算。也就是说当你需要某个函数的结果再向下延续使用时候必须有返回值。

对比下面两段代码:

希望python自写的函数报错了能重新自动运行_return返回值


8.4.2禁止函数修改列表

当我们需要保留原有列表的时候可以采用先创建个列表副本,让函数操作这个列表副本,这样就保留了原有的列表。

函数(列表变量[:])

[:]切片法,列表中的全部元素。

把上面程序中的

print_models(unprinted_designs, completed_models)
改为
print_models(unprinted_designs[:], completed_models)

就可以实现函数对列表unprinted_designs的副本操作。
练习8-9:消息

def show_messages(messages):
	for message in messages:
		print(message)
user_messages = ['我是tachyon', '我姓xue', '我来自中国']
show_messages(user_messages)
结果:
我是tachyon
我姓xue
我来自中国
[Finished in 0.1s]

练习8-10:发送消息

def show_messages(messages):
	for message in messages:
		print(message)
def send_messages(user_messages, sent_messages):
	while user_messages:
		current_message = user_messages.pop()
		print(current_message)
		sent_messages.append(current_message)
user_messages = ['我是tachyon', '我姓xue', '我来自中国']
show_messages(user_messages)
sent_messages = []
send_messages(user_messages, sent_messages)
print(user_messages)
print(sent_messages)
结果:
我是tachyon
我姓xue
我来自中国
我来自中国
我姓xue
我是tachyon
[]
['我来自中国', '我姓xue', '我是tachyon']
[Finished in 0.1s]

练习8-11:消息归档

def show_messages(messages):
	for message in messages:
		print(message)
def send_messages(user_messages, sent_messages):
	while user_messages:
		current_message = user_messages.pop()
		print(current_message)
		sent_messages.append(current_message)
user_messages = ['我是tachyon', '我姓xue', '我来自中国']
show_messages(user_messages)
sent_messages = []
send_messages(user_messages[:], sent_messages)
print(user_messages)
print(sent_messages)
结果:
我是tachyon
我姓xue
我来自中国
我来自中国
我姓xue
我是tachyon
['我是tachyon', '我姓xue', '我来自中国']
['我来自中国', '我姓xue', '我是tachyon']
[Finished in 0.1s]