六、函数:
1、定义:
组织好的、可重复使用的、用来实现特定功能的代码段,将功能封装在函数内,可供随时随地重复利用,提高代码的复用性,减少重复代码,提高开发效率
2、语法:
def 函数名(可传参数):
函数体
return 返回值
调用:变量 = 函数(参数)
注意:
(1)先定义函数,后调用函数
(2)参数不需要时,可以省略;返回值不需要时,可以省略
(3)函数定义中的参数,称之为形式参数;函数调用中的参数,称之为实际参数;函数的参数数量不限,使用逗号分隔开;传入参数的时候,要和形式参数一一对应,逗号隔开
(4)函数体在遇到return后就结束了,所以写在return后的代码不会执行
3、嵌套调用:
在一个函数中,调用另外一个函数,如函数A中执行到调用函数B的语句,会将函数B全部执行完成后,继续执行函数A的剩余内容
4、局部变量作用范围在函数内部,在函数外部无法使用;全局变量在函数内部和外部均可使用
5、将函数内定义的变量声明为全局变量,使用global关键字:global 变量
6、函数的参数:
(1)位置参数:根据参数位置来传递参数
(2)关键字参数:通过“键=值”形式传递参数,可以不限参数顺序;可以和位置参数混用,位置参数需在前
(3)缺省参数:不传递参数值时会使用默认的参数值;默认值的参数必须定义在最后
(4)不定长参数:位置不定长传递以*号标记一个形式参数,以元组的形式接受参数,形式参数一般命名为args;关键字不定长传递以**号标记一个形式参数,以字典的形式接受参数,形式参数一般命名为kwargs
7、函数本身是可以作为参数,传入另一个函数中进行使用的,将函数传入的作用在于: 传入计算逻辑,而非传入数据。
8、匿名函数:使用lambda关键字进行
(1)定义:lambda 传入参数: 函数体(一行代码)
(2)注意:匿名函数用于临时构建一个函数,只用一次的场景;匿名函数的定义中,函数体只能写一行代码,如果函数体要写多行代码,不可用lambda匿名函数,应使用def定义带名函数
9、闭包
(1)引述:函数外定义全局变量,全局变量有被修改的风险,需要使用闭包避免
(2)定义:在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包
(3)例子1
def account_create(initial_amount=0):
def atm(num, deposit=True):
nonlocal initial_amount
if deposit:
initial_amount += num
print(f"存款:+{num},账户余额:{initial_amount}")
else:
initial_amount -= num
print(f"取款:-{num},账户余额:{initial_amount}")
return atm
fn = account_create()
fn(300)
fn(200, False)
# -->输出:
# 存款:+300,账户余额:300
# 取款:-200,账户余额:100
(4)例子2:修改外部函数变量的值,需要使用nonlocal关键字修饰外部函数的变量才可在内部函数中修改它
def outer(num1):
def inner(num2):
nonlocal num1
num1 += num2
print(num1)
return inner
fn = outer(10)
fn(10)
fn(10)
# -->输出:
# 20
# 30
(5)闭包注意事项
优点:使用闭包可以让我们得到:无需定义全局变量即可实现通过函数,持续的访问、修改某个值;闭包使用的变量的所用于在函数内,难以被错误的调用修改
缺点:由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放。一直占用内存
10、装饰器
(1)定义:装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能
(2)代码释义:希望给sleep函数增加一个功能:在调用sleep前输出:我要睡觉,在调用sleep后输出:我起床了
import random
import time
def sleep():
print("睡眠中......")
time.sleep(random.randint(1,5))
(2-1)装饰器的一般写法(闭包写法)
def outer(func):
def inner():
print("我要睡觉了")
func()
print("我起床了")
return inner
def sleep():
import random
import time
print("睡眠中......")
time.sleep(random.randint(1,5))
fn = outer(sleep)
fn()
# -->输出:
# 我要睡觉了
# 睡眠中......
# 我起床了
(2-2)装饰器的语法糖写法,使用@,定义在目标函数上。装饰器就是使用创建一个闭包函数,在闭包函数内调用目标函数,可以达到不改动目标函数的同时,增加额外的功能
def outer(func):
def inner():
print("我要睡觉了")
func()
print("我起床了")
return inner
@outer
def sleep():
import random
import time
print("睡眠中......")
time.sleep(random.randint(1,5))
sleep()
# -->输出:
# 我要睡觉了
# 睡眠中......
# 我起床了