python函数闭包、装饰器

一、装饰器

1、什么是装饰器

装饰器本质上也是函数,应用到了高阶函数以及闭包的知识(关于闭包会在下文解释)可以为其他函数实现一些新的功能

  • 装饰器不会修改被装饰的函数的源代码
  • 不修改被修饰函数的调用方式

2、简单装饰器的实现

有一个自定义函数,希望可以实现打印此函数运行时间的功能

import time
def test():
    time.sleep(3)
    print("this is test")

由于装饰器的原则是不能改变函数源代码,因此不能直接修改test函数

def timer(func): #将函数作为参数传入,高阶函数的应用 
	t1 = time.time() #记录开始时间 
	func() 
	t2 = time.time() #记录函数运行完毕的时间
	print("此函数一共运行了%f"%(s2-s1))

timer(test)
###########
#this is test
#此函数一共运行了3.003660

由于装饰器的意义在于不用改变原函数的调用方式,因此这个方式也需要改进

def timer(func):
    def wrapper(*arg,**kwargs): 
    #使用函数的嵌套,由于被修饰函数可能会有参数,因此需要用不定长函数进行接收
        s1 = time.time()
        res = func(*arg,**kwargs) #由于此函数为上层传入的变量,因此此嵌套函数是为闭包的使用方式
        s2 = time.time()
        print("此函数一共运行了%f"%(s2-s1))
        return res #返回原函数的返回值
    return wrapper
name = "hello"

@timer  #timer后面没有加(),那@timeer就是test = timer(test) 的意思,
def test(name):
    time.sleep(3)
    print("%s this is test"%name)
test()

*代表变量解压,*(1,2,3,4)会将数组中的值依次拿出,a,b,c=(1,2,3)这种赋值形式也可以将元祖中的值依次赋给a,b,c

给装饰器传入参数

def top_timer(type="test")
	def timer(func):
	    def wrapper(*arg,**kwargs): 
	    #使用函数的嵌套,由于被修饰函数可能会有参数,因此需要用不定长函数进行接收
	    	print("传入的type为%s"%type)
	        s1 = time.time()
	        res = func(*arg,**kwargs) #由于此函数为上层传入的变量,因此此嵌套函数是为闭包的使用方式
	        s2 = time.time()
	        print("此函数一共运行了%f"%(s2-s1))
	        return res #返回原函数的返回值
	    return wrapper
	return timer

@top_timer(type="hello")
#参数会传入闭包中
#当语法糖后面是一个有参数的函数,那首先会执行后面的函数
#top_timer(type="hello")返回值是timer,那执行后是@timer
#因此最后还是执行 test = timer(test),而参数也已经传入

二、闭包

1、什么是闭包

闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境),简单来说函数的闭包就是当内嵌函数体内引用到体外的变量时,将会把定义时涉及到的引用环境和函数体打包成一个整体(闭包)返回。相当于一个函数A包裹了一个函数B,而引用函数A时会把函数B中的东西都释放出来,是嵌套函数的高级用法。

2、闭包的简单实例

def ExFunc(n):
     sum=n
     def InsFunc():
             return sum+1 #此嵌套函数引用了体外的变量
     return InsFunc
myFunc=ExFunc(10) #将引用环境 sum=10 一起和函数打包进行返回
myFunc()
# 11

3、关于闭包的错误例子

这段程序的本意是要通过在每次调用闭包函数时都对变量a进行递增的操作。但在实际使用时,会报错找不到a变量。
原因是因为在进入bar中寻找变量a,而在函数中在等号左边的都会被函数定义为局部变量,在函数已经存在同名变量的前提下是不会去寻找上一级变量的,因此报错。

def foo():  
    a = 1  
    def bar(): 
    	#在此处插入一个 nonlocal a 就可以解决此问题
        a = a + 1  
        return a  
    return bar
c = foo()
print(c())

这个例子中,一般以为输出应该是2,3,4,实际应该为4,4,4。
原因是因为在python中只有当函数执行时才会去寻找变量的值,因此当定义函数时,当i遍历完毕后并没有被释放,i驻留在内存中的值为2。

flist = []  
for i in range(3):  
    def foo(x): print x + i  
    flist.append(foo)  #flist中存储的是foo函数函数地址
for f in flist:  
    f(2)  # f=foo --> foo(2) --> print 2+2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
闭包装饰器是一种特殊的装饰器,它使用闭包的概念来实现。闭包是指一个函数可以访问并操作其外部函数中定义的变量。在Python中,闭包装饰器可以用于给函数添加额外的功能,同时保持函数的原始定义不变。 引用中的示例展示了装饰器传参的形式。在这个例子中,outer函数是一个装饰器,它将inner函数作为子函数返回,并在inner函数中添加了额外的功能。通过使用@outer装饰器语法,我们可以在add函数上应用outer装饰器,从而在调用add函数时执行装饰器中的代码。 引用中的示例展示了多层装饰器的使用。在这个例子中,outer1和outer2函数分别是两个装饰器,他们都返回一个inner函数。通过使用@outer1和@outer2装饰器语法,我们可以在outers函数上应用这两个装饰器,并在调用outers函数时按照装饰器的定义顺序执行相关的代码。 引用提供了关于Python闭包装饰器的使用方法的总结。这篇文章通过示例代码详细介绍了闭包装饰器的使用,对于学习和工作有一定的参考价值。 引用中的示例展示了装饰器的形式。在这个例子中,outer函数是一个装饰器,它将inner函数作为子函数返回,并在inner函数中添加了额外的功能。通过使用@outer装饰器语法,我们可以在add函数上应用outer装饰器,从而在调用add函数时执行装饰器中的代码。 综上所述,Python闭包装饰器是一种利用闭包概念实现的特殊装饰器,可以用于给函数添加额外的功能。这种装饰器可以通过装饰器传参的形式、多层装饰器的形式或普通的装饰器形式来实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值