函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段
print()就是一个函数,它是Python提前为我们封装好的
认识函数
例:自定义一个函数
# 自定义一个函数
def say_hello():
"""向大家说你好"""
print('Hello, everybody!')
# 调用写好的自定义函数
say_hello()
输出:
Hello, everybody!
第一行代码中,def
是用来定义函数的关键字,然后是自定义的一个函数名字say_hello
,函数名字后面一字要加上一对()
,定义完函数后记得在后面加一冒号;冒号下面的有缩进的代码都属于这个函数的函数体,即这个函数要实现的功能,在这里,函数say_hello的功能是打印Hello, everybody!
注意,"""向大家说你好"""这行注释叫作==文档字符串==,它写在函数体的第一行,用来描述这个函数是什么的;它的意义在于方便开者理解函数意义,写注释是一个好习惯
say_hello()
是调用该函数语句
函数的参数
上例中的say_hello()
是一个无参函数
say_hello()
目前的功能是对所有人说Hello,如果想对小红说Hello,则需要再定义一个函数:
# 自定义一个函数
def say_hello_to_xiaohong():
"""向大家说你好"""
print('Hello, xiaohong!')
# 调用写好的自定义函数
say_hello_to_xiaohong()
那如果要对小明说Hello呢?再写一个函数?这样太麻烦了!我们可以将不断变化的人名提取出来,做为参数传递,这个函数就不必再关注要对谁说Hello了
# 自定义一个函数
def say_hello(name):
"""向大家说你好"""
print('Hello, '+name+"!")
# 调用写好的自定义函数
say_hello('xiaohong')
say_hello('xiaoming')
输出:
Hello, xiaohong!
Hello, xiaoming!
def say_hello(name):
中的name被称作形参
say_hello('xiaohong')
调用函数时传递的具有实际值的参数被称作实参
向函数传递多个参数
# 定义一个打印食物名称与价格的函数
def show_food_price(food,price):
"""打印食物名称与价格"""
print("food:"+str(food))
print("price:"+str(price))
# 打印牛奶信息
show_food_price('milk',3.2)
# 打印苹果的信息
show_food_price('apple',5)
输出:
food:milk
price:3.2
food:apple
price:5
一看就明白,多个参数之间只要用逗号进行分隔开即可
这里因为传递的price参数是个数值,因此在打印的时候别忘记用str()将其转换成字符串
假如上面的例子,将食物名称与价格这两个参数传递顺序变换一下,结果会怎么样?
# 定义一个打印食物名称与价格的函数
def show_food_price(food,price):
"""打印食物名称与价格"""
print("food:"+str(food))
print("price:"+str(price))
# 打印牛奶信息
show_food_price(3.2,'milk')
# 打印苹果的信息
show_food_price(5,'apple')
输出:
food:3.2
price:milk
food:5
price:apple
可以看出,一旦实参顺序与形参顺序不一致,将会导致令人不悦的后果
要求实参顺序与形参顺序一致的值参方式叫帮位置实参
如果怕将顺序写错,则可以采用关键字实参,例:
# 定义一个打印食物名称与价格的函数
def show_food_price(food,price):
"""打印食物名称与价格"""
print("food:"+str(food))
print("price:"+str(price))
# 打印牛奶信息
show_food_price(price=3.2,food='milk')
# 打印苹果的信息
show_food_price(food='apple',price=5)
输出:
food:milk
price:3.2
food:apple
price:5
关键字实参可显性的指出形参的名称并为其赋值,这样即不用再关注形参的顺序
上例的函数有两个形参,那如果在调用的时候只传递了一个实参会怎么样呢?
# 定义一个打印食物名称与价格的函数
def show_food_price(food,price):
"""打印食物名称与价格"""
print("food:"+str(food))
print("price:"+str(price))
# 打印牛奶信息
show_food_price('milk')
输出:
Traceback (most recent call last):
File "C:/Users/Administrator/AppData/Local/Programs/Python/Python37-32/a.py", line 7, in <module>
show_food_price('milk')
TypeError: show_food_price() missing 1 required positional argument: 'price'
可以看出,函数还有一个参数price,但我们没有给它传递值,函数在执行的时候无法处理这种情况
可以将参数price设置默认值,即可避免此种情况,如下:
# 定义一个打印食物名称与价格的函数
def show_food_price(food,price=0):
"""打印食物名称与价格"""
print("food:"+str(food))
# 当价格值是默认值时,不做任何处理
if price != 0:
print("price:"+str(price))
# 打印牛奶信息
show_food_price('milk')
# 打印苹果的信息
show_food_price('apple',5)
输出:
food:milk
food:apple
price:5
注意:如果多个参数中,有指定默认值 的情况,则指定默认值的形参要放在没有设置默认值的形参之后,因此在使用位置实参的时候,会从第一个开始匹配
位置实参与关键字实参可以混合使用,如下:
# 定义一个打印食物名称与价格的函数
def show_food_price(food,price=0):
"""打印食物名称与价格"""
print("food:"+str(food))
# 当价格值是默认值时,不做任何处理
if price != 0:
print("price:"+str(price))
# 打印牛奶信息
show_food_price('milk',price=5)
输出:
food:milk
price:5
让函数返回你想的数据
函数可以返回任何类型数据,数值、字符串、列表、字典……
# 定义一个打印食物名称与价格的函数
def show_food_price(food,price=0):
"""返回食物名称与价格"""
message = "food:"+str(food)+"\nprice:"+str(price)
return message
# 打印牛奶信息
return_message = show_food_price('milk',price=5)
print(return_message)
输出:
food:milk
price:5
这里做了一些修改,将食物的名称与价格拼接成一个字符串,将通过关键字return
将字符串返回
在调用函数的时候,return_message
变量接收函数的返回值,即message
,然后将其打印输出
上面的代码设置了默认的price,因此,函数体内还要对默认值做个处理,如下:
# 定义一个打印食物名称与价格的函数
def show_food_price(food,price=0):
"""返回食物名称与价格"""
message = ""
message1 = "food:"+str(food)
message2 ="\nprice:"+str(price)
if price != 0:
message = message1 + message2
else:
message = message1
return message
# 打印牛奶信息
return_message = show_food_price('milk',price=5)
print(return_message)
# 打印苹果信息
print(show_food_price('apple'))
输出:
food:milk
price:5
food:apple
下面再演示返回字典的例子
def show_food_price(food,price=0):
"""返回食物名称与价格"""
food_dic = {}
food_dic[food] = price
return food_dic
# 打印牛奶信息
return_message = show_food_price('milk',price=5)
print(return_message)
输出:
{'milk': 5}
使用函数将上节中为小红定制的系统进行升级
def initialize():
"""初始化食物清单列表,并将其返回"""
foods = [
{'tomato': 3, 'potato': 2, 'onion': 4},
{'apple': 5, 'banana': 3.3},
{'beef': 23, 'pork': 14, 'chicken': 19.8, 'fish': 9.7}
]
return foods
def get_food(foods,food):
"""查看是否有顾客想要的食物"""
find_food = ""
# 从小红的食物清单里查看是否有顾客想要的食物
for food_list in foods:
if food in food_list.keys():
find_food = food
print("We have " + find_food + ". Please wait a moment")
break
# 如果找到顾客想要的食物,将其赋值给变量find_food
# 如果该变量是空字符串,证明没有找到顾客想要的食物
if find_food == "":
print("Sorry, there are no " + food + " here")
def find_food(foods):
"""根据用户输入的食物进行答复"""
# 退出标志
exit = False
while not exit:
# 获取用户输入的食物名称
txt_value = input("Please tell me what kind of food you want:")
if txt_value == 'quit':
exit = True
get_food(foods,txt_value)
# 初始化食物列表
foods = initialize()
# 将食物列表传递给find_food函数,系统开始工作
find_food(foods)
# 上面两行等同于
# find_food(initialize())
输出:
Please tell me what kind of food you want:apple
We have apple. Please wait a moment
Please tell me what kind of food you want:potato
We have potato. Please wait a moment
Please tell me what kind of food you want:
通过重构,将原来的代码进行了分类处理,即将数据初始化的工作封装为一个函数,将寻找食物的工作封装为一个函数,将循环工作的代码又封装成一个函数,这样,代码的可读必,可重用性变得更高了
在这个例子中看到,foods列表被当作一个参数传递给了相关函数,实际上,在函数体内可以对列表进行修改,如下:
# 食物清单
foods = [
{'tomato': 3, 'potato': 2, 'onion': 4},
{'apple': 5, 'banana': 3.3},
{'beef': 23, 'pork': 14, 'chicken': 19.8, 'fish': 9.7}
]
def print_food(foods):
"""打印foods列表中的食物名称"""
for food_dic in foods:
for food in food_dic.keys():
print(food)
# 将打印完毕的食物的价格改为0
food_dic[food] = 0
print(foods)
print_food(foods)
输出:
tomato
potato
onion
apple
banana
beef
pork
chicken
fish
[{'tomato': 0, 'potato': 0, 'onion': 0}, {'apple': 0, 'banana': 0}, {'beef': 0, 'pork': 0, 'chicken': 0, 'fish': 0}]
foods列表不仅可以被当作参数传递,而且在函数体内对其内容进行修改后,可直接改变列表的内容
因为是修改,所以这里使用了for循环,在修改的过程中,使原有的列表的长度发生了变化,则要使用while循环,否则会报错