概述
函数解决了复用的问题,比如一段代码需要在多个地方复用。
定义&调用函数
#定义
def function_name([参数]...):
代码
#调用
function_name()
参数
一个参数和多个参数
#一个参数
def user_name(userName):
print('您输入的用户名是:{}'.format(userName))
user_name('liqi')
#多个参数
def msg(uName,uAge,uMoney):
print('你的名字:{},你的年龄:{},你的工资:{}'.format(uName,uAge,uMoney))
msg('lq',27,500)
-----------
输出:
您输入的用户名是:liqi
你的名字:lq,你的年龄:27;你的工资:500
默认参数和关键字参数
默认参数就是提前给参数一个默认值。后续调用函数如果赋值了,新的值将覆盖默认值。
关键字参数是函数调用时,以key=value的形式指定值是付给哪个参数的。这种关键字参数赋值时,是可以不考虑顺序的。
# 默认参数&关键字参数
def msg_default_key(uName, uAge, uMoney=100, uHobby='篮球'):
print('你的名字:{},你的年龄:{},你的工资:{},你的爱好:{}'.format(uName, uAge, uMoney, uHobby))
msg_default_key('lq', 27, 500, '足球') #默认参数有赋值
msg_default_key('lq', 27) #默认参数未赋值
msg_default_key('lq', 27, uMoney=500) #关键字参数
msg_default_key(uName='lq', uHobby='看电影', uMoney=1000, uAge=27) #关键字参数顺序可不一致
-----------
输出:
你的名字:lq,你的年龄:27,你的工资:500,你的爱好:足球 #默认参数有赋值
你的名字:lq,你的年龄:27,你的工资:100,你的爱好:篮球 #默认参数未赋值
你的名字:lq,你的年龄:27,你的工资:500,你的爱好:篮球 #关键字参数
你的名字:lq,你的年龄:27,你的工资:1000,你的爱好:看电影 #关键字参数顺序可不一致
不定长参数
*args #可变长参数,传值后是元组
**kwargs #可变长关键字参数,传值后是字典
# 不定长参数
# *args
# *kwargs
def show_name(*name):
print(name)
show_name('阿黄', '啊蓝', '啊红')
def show_book(**book):
print(book)
show_book(book_name='西游记', price=99)
----------
输出:
('阿黄', '啊蓝', '啊红')
{'book_name': '西游记', 'price': 99}
函数的装包&拆包
函数定义时:*表示装包成元组;**表示装包成字典
函数调用时(传参):*表示将元组/列表拆包;**表示将字典拆包
# 不定长参数
# *args
# *kwargs
def show_name(*name): # 函数定义时的*——装包
print(name)
show_name('阿黄', '啊蓝', '啊红') # 由于函数定义时是*args,所以此处将传递的值装包
list1 = ['阿黄', '啊蓝', '啊红']
tuple1 = ('阿黄', '啊蓝', '啊红')
show_name(*list1) # 函数调用时的*——拆包list
show_name(*tuple1) # 函数调用时的*——拆包tuple
def show_book(**book): # 函数定义时的**——装包
print(book)
show_book(book_name='西游记', price=99)
dict1 = {'book_name': '西游记', 'price': 99}
show_book(**dict1) # 函数调用时的**——拆包dictionary
-----------
输出:
('阿黄', '啊蓝', '啊红')
('阿黄', '啊蓝', '啊红')
('阿黄', '啊蓝', '啊红')
{'book_name': '西游记', 'price': 99}
{'book_name': '西游记', 'price': 99}
Q:为什么函数用了装包,调用时候如果使用了列表/元组/字典,要拆包?
A:不拆包会有报错。函数定义时装包,是要将“零散的”值装包成 列表/元组/字典。如果已经是 列表/元组/字典 ,列表和元组执行装包则会嵌套,字典则直接会报错,都存在问题。
错误示例:
列表/元组不拆包,嵌套
def show_name(*name):
print(name)
list1 = ['阿黄', '啊蓝', '啊红']
tuple1 = ('阿黄', '啊蓝', '啊红')
show_name(list1)
show_name(tuple1)
----------
输出:
(['阿黄', '啊蓝', '啊红'],) #列表嵌套
(('阿黄', '啊蓝', '啊红'),) #元组嵌套
字典不拆包,直接报错如下图
函数返回值-return
return 返回一个值
def sum_num(*num):
total = sum(num)
return total
result = sum_num(1, 2, 3, 4, 5)
print("求和:", result)
--------
输出:
求和: 15
return返回多个值
def get_min_max(numbers):
min_num = min(numbers)
max_num = max(numbers)
return min_num, max_num
list1 = [i for i in range(10)]
result = get_min_max(list1)
min_num, maxnum = get_min_max(list1)
print(result)
print(min_num, maxnum)
---------
输出:
(0, 9) #多个值,其实是返回的一个元组
0 9
return也可以直接单独使用,不带任何返回值。用处类似于循环中的break,直接跳出函数。
函数嵌套
nonlocal-调用外部函数变量
此处可以结合全局变量和局部变量的global关键字一起看。
global关键字可以在局部调用全局的变量。而嵌套函数中,内部函数如果想调用外部函数的变量,外部函数的变量不属于全局变量,所以需要使用nonlocal关键字调用。
def outside(num):
a = 100
def inside():
nonlocal a
b = a + num
print(b)
inside()
outside(11)
---------------
输出:
111
闭包
闭包的使用场景:装饰器
满足以下三个条件的函数为闭包
- 嵌套函数
- 内部函数调用了外部函数的变量
- 外部函数返回值是内部函数
#嵌套函数
def outside(num):
a = 100
def inside():
nonlocal a #内部函数调用外部函数变量
b = a + num
print(b)
return inside #返回值是内部函数
result = outside(11) #result接收内部函数地址
result()
---------
输出:
111