函数的作用
将具有特定功能的代码块进行封装,方便以后重复使用
return 的作用
函数调用时,return 的作用是停止运行return后面的代码并返回return后的值,若return后面有没有其他东西,则返回 None
return 返回多个值:return a, b写法,返回多个数据的时候,默认会组包成元组返回,即return (a,b),return后面可以书写列表、元组或字典,返回多个值
函数参数(分别从定义函数,调用函数说明)
定义函数中的参数是“形参”
调用函数中的参数是“实参”
形参的改变不用影响实参,但实参的改变会影响形参。
-
定义函数:
def 函数名(形参):
执行代码 -
调用函数
函数名(实参)
位置参数
位置参数:调用函数时根据函数定义的参数位置来传递参数。
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('TOM', 20, '男')
注:
- 传递和定义参数的顺序及个数必须一致。
- 位置参数就是对号入座,不能多也不能少
关键字参数
函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('Rose', age=20, gender='女')
user_info('小明', gender='男', age=16)
注:
- 关键字参数是以key=value的方式传参
- 函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。
缺省参数
缺省参数也叫默认参数,用于定义函数,为形参提供默认值,调用函数时可不传该默认参数的值
注意:
- 默认参数是形参, 必须写在位置参数后面
- 调用函数时, 可以不传参给默认参数, 不传参则使用默认值,传参则使用传过来的值
- 设置默认参数的好处:
- 减少函数大量反复的固定值传参
- 为用户预留可操作的入口
def user_info(name, age, gender='男'):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('TOM', 20)
user_info('Rose', 18, '女')
注意:函数调用时,如果为缺省参数传值则修改默认参数值;否则使用这个默认值
不定长参数
不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。
- 包裹位置传递
def user_info(*args):
print(args)
# ('TOM',)
user_info('TOM')
# ('TOM', 18)
user_info('TOM', 18)
- 包裹关键字传递
def user_info(**kwargs):
print(kwargs)
# {'name': 'TOM', 'age': 18, 'id': 110}
user_info(name='TOM', age=18, id=110)
注意:
- 不定长参数属于形参
- *args用于接收没有形参接收的位置参数,把这些没人接收的位置参数包裹成一个元组(tuple),保存起来
- **kwargs 用于接收没有形参接收的关键字参数, 把这些没人接收的关键字参数包裹成一个字典(dict),保存起来
- 编写规范: *args写在位置参数后, 默认参数前, **kwargs写在默认参数后
- 无论是包裹位置传递还是包裹关键字传递,其实都是一个组包的过程
函数参数是值传递还是引用传递(分别对不可变和可变类型进行说明)
定义
- 值传递: 指在传递过程中将实际参数的值复制一份传递给形式参数
- 引用传递:将实际参数的引用传递给实际参数,这样二者就会指向同一块内存地址,在函数执行过程中对形 式参数进行了修改,形式参数也会一并被修改
# 1. int类型
a = 1
b = a
print(b) # 1
print(id(a)) # 140708464157520
print(id(b)) # 140708464157520
a = 2
print(b) # 1,说明int类型为不可变类型
print(id(a)) # 140708464157552,此时得到是的数据2的内存地址
print(id(b)) # 140708464157520
# 2. 列表
aa = [10, 20]
bb = aa
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
aa.append(30)
print(bb) # [10, 20, 30], 列表为可变类型
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
总结:不可变类型传参属于值传参,可变类型传参属于引用传参。值传参和引用传参最大的区别就是看内存地址是否有改变
变量的作用域(局部变量和全局变量)
- 全局:函数体内外都能生效
- 局部:当前函数体内部生效
如何交换两个变量的值
- a,b=b,a
- 使用中间值c, c = a , a = b , b = c
拆包的使用
元组
n1,n2,n3,n4=(1,2,3,4)
字典
a,b={‘name’: ‘TOM’, ‘age’: 18}
a,b 为key
lambda函数
匿名函数:如果一个函数有一个返回值,并且只有一句代码,可以使用 lambda简化。
格式:lambda 参数列表 : 表达式
f=lambda a,b:a+b
resulut=f(1,2)
print(result) # 3
注意:
- lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。
- lambda表达式能接收任何数量的参数但只能返回一个表达式的值
- 匿名函数中不能使用 if 语句、while 循环、for 循环, 只能编写单行的表达式,或函数调用都可以.但可以接三目运算符(a if a>b else b)
- 匿名函数中返回结果不需要使用 return, 表达式的运行结果就是返回结果
- 匿名函数中也可以不返回结果. 例如: lambda : print(‘hello world’)
递归函数
- 函数内部自己调用自己
- 必须有出口
# 3 + 2 + 1
def sum_numbers(num):
# 1.如果是1,直接返回1 -- 出口
if num == 1:
return 1
# 2.如果不是1,重复执行累加并返回结果
# 3以内的数字累加和 = 3+ 2以内的数字累加和
return num + sum_numbers(num-1)
sum_result = sum_numbers(3)
# 输出结果为6
print(sum_result)
什么是闭包函数,其作用是?怎么判断函数是闭包函数
定义
- 函数嵌套
- 内部函数使用外部函数变量
- 外部函数返回了内部函数
作用
闭包可以保存外部函数内的变量,不会随着外部函数调用完而销毁。
注意点:
由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,消耗内存。
说出其结果和原因
def fn(num, lis=[]):
for i in range(1, num + 1):
lis.append(i)
print(lis)
fn(2, [])
fn(2)
fn(3)
[1,2]
[1,2]
[1,2,1,2,3]
函数属于关键字传参,fn(2, [])形参num = 2 , lis = [],将1,2 添加到lis中。fn(2),lis=[], fn(2)结束后lis=[1,2],调用f(3)时,在lis=[1,2]后添加元素。由于列表传参属于引用传参,f(2),f(3)没有重新定义列表,所有他们的内存地址都是一样的。