浅聊python函数装饰器和闭包

1. 直观认识一下装饰器

装饰器是可以调用的对象,其参数是另一个函数(被修饰的函数),被修饰的函数进入装饰器以后有两种处理方式; 1) 被处理,单纯解释一下就是可能在原函数的基础上加上另外的操作,然后返回;2)被替换为另一个函数或者可调用的对象

下面看看看一个修饰器的直观印象

@decorate
def target():
	print("running target()")
def target():
	print("running target()")
target = decorate(target)#表示target函数作为参数传给修饰器

上述例子就是修饰器的最用,上述例子执行完毕得到的tatget函数不一定是原来的target函数了,而是被decorate修饰以后的函数;具体需要看修饰函数的具体行为是怎样的;

2.修饰函数的特点:

  1. 在加载模块的时候立即执行
  2. 能把被修饰的函数替换成其他函数

能把被修饰的函数替换成其他函数
例子如下:

# 自定义的修饰器,该修饰器的作用就是将原始被修饰的函数的函数名替换为inner
def deco(func):
	def inner():
		print("running inner()")
	return inner
	
@deco
def target():
	print("running target()")
>> target()
output: running inner()
target()->inner()->"rinning inner()"

在加载模块的时候立即执行

def deco(fun):
    def f2():
        print("222")
    return f2

@deco
def f1():
    print("123")
    
def f3():
    print("333")
    
def main():
    print("start")
    print(deco)
    f3()
    
if __name__=='__main__':
    main()
start
<function deco at 0x000002DD3BB32820>
333

清晰可见,这里的调用main函数以后应该是先输出"start",但是这里很明显是直接西安调用了修饰器函数echo,所以装饰器函数在加载模块的时候会立即执行;

正是因为装饰器在导入的时候就执行,所以python程序就有了导入时和运行时的区别;函数装饰器在导入模块的时候立即执行,而被修饰的函数只有在明确调用的时候才运行

3. 变量的作用域规则

先来说说为为什么提到作用域

b = 6
def f(a):
	print(a)
	print(b)
	b = 4
f(3)

这段代码在运行的时候会报错,原因是python在编译函数的时候,把b当作了局部变量,因为在使用b的时候还没有给他赋值(语句b=4在print(b)后);所以就造成了错误

local variable 'b' referenced before assignment

4.闭包与nonlocal

紧接第三部分,闭包是延伸了作用域的函数,包含了函数定义体中的应用,但是不在定义体中定义的非全局变量;例子如下:

def make_averager():
	series = []
	def averager(new_value):
		series.append(new_value)
		total = sum(series)
		return total/len(series)
	return averager
avg = make_averager()
>>avg(10)
>>10.0
avg(11)
>> 10.5
avg(12)
11.0

其中列表series就是没有在闭包函数体中定义但是在其函数引用的变量,注意在闭包函数体内,使用append函数其实是对变量series进行了修改的
在python中列表是可以被修改的,

闭包函数体示意图;
在这里插入图片描述
这里的自由变量的变量类型是可变的,但是如果自由变量是不可变得类型,比如数字、字符串和元组来说,只能读取不能更新;见下面得例子

def make_averager():
	count = 0
	total = 0
	def averager(new_value):
		count+=1
		total += new_value
		return total/count
	return averager

这个例子就会出错,因为自由变量count和total作为不可变类型,在闭包函数中不能更新;所以就引入一个关键字nonlocal,作用就是把变量标记为自由变量

def make_averager():
	count = 0
	total = 0
	def averager(new_value):
		nonlocal count,total
		count+=1
		total += new_value
		return total/count
	return averager
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星光技术人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值