闭包、装饰器

闭包

闭是封闭(函数中的函数),包是包含(该内部函数对外部函数作用域而非全局作用域变量的引用。)

闭包:

  • 内部函数外部函数作用域里的变量的引用
  • 函数内的属性,都是有生命周期,都是在函数执行期间
  • 闭包内的闭包函数私有化了变量,
def foo():
    print("in foo()")
    def bar ():
        print("in bar()")
#1. 直接运行内部函数报错
# bar()
# 
# 2.先运行外部函数,再运行内部函数,依然会报错
# foo()
# bar()

由于作用域的问题,函数内的属性都是有生命周期的,只有在函数执行期间

在这段代码,只有调用foo()是,内部的print()及bar()才能存活。

现在我们为了让foo()内bar()存活,就是调用bar()

  • 把bar()函数返回给函数
def foo():
    print("in foo()")

    def bar():
        print("in bar()")
    return bar

var = foo()
var()

内部函数对外部函数作用域的引用

—>参数调用

def foo():
    a = 66
    print("in foo()")

    def bar(num):
        print("in bar()")
        print(a + num )
    return bar

var = foo()
var(22)
# in foo()
# in bar()
# 88

li = [1,2,3,4,5]

def foo(obj):
    print("foo",obj)

    def bar():
        obj[0] += 1
        print("bar",obj)
    return bar
# 程序在执行时,foo()函数返回给了内部定义的bar()函数
var = foo(li) # 将返回值赋值给var
var()
var()
var()
# foo [1, 2, 3, 4, 5]
# bar [2, 2, 3, 4, 5]
# bar [3, 2, 3, 4, 5]
# bar [4, 2, 3, 4, 5]

装饰器

@func1
def func():
    print('aaa')

装饰器存在的意义

  • 不影响原有函数的功能
  • 可以添加新功能

一般常见的,比如拿到第三方API接口,第三方不允许修改这个接口,需要使用装饰器。

装饰器本身是一个函数,作用是为现有存在的函数,在不改变函数的基础上,添加一些功能进行装饰。

它是以闭包的形式实现的。

在使用装饰器函数时,在被装饰的函数的前一行,使用@装饰器函数名形式来进行装饰。

Demo:

现在在一个项目中,有很多函数,由于我们的项目越来越大,功能也越来越多,导致程序越来越慢。

其中一个功能函数的功能,是实现一百万次的累加。

def my_count():
    s = 0
    for i in range(1000001):
        s += i
    print("sum: ",s)

计算时间


import time
def my_count():
    s = 0
    for i in range(1000001):
        s += i
    print("sum: ",s)
start = time.time()
my_count()
end = time.time()
print("执行时间为:",(end - start))
# sum:  500000500000
# 执行时间为: 0.0608363151550293

每一个函数都进行时间计算,此方式比较麻烦,代码过于多余。

import time
def my_count():
    s = 0
    for i in range(1000001):
        s += i
    print("sum: ",s)

def count_time(func):
        start = time.time()
        func()
        end = time.time()
        print("执行时间为:", (end - start))

count_time(my_count) # 仍然更改了调用方式
# sum:  500000500000
# 执行时间为: 0.054853200912475586

修改之后,定义一个函数来实现时间计算功能。

使用时需要将对应的函数传入到时间计算函数中。

但是启用时间计算功能时更改了my_count的函数调用方式。

import time
def count_time(func):
    def wrapper():
        start = time.time()
        func()
        end = time.time()
        print("执行时间为:", (end - start))
    return  wrapper

@count_time
def my_count():
    s = 0
    for i in range(1000001):
        s += i
    print("sum: ",s)
    
my_count()

这样实现的好处,定义闭包函数后,只需要通过@装饰器函数名形式的装饰器语法,就可以将@装饰器函数名加到要装饰的函数前即可

这种不改变原有函数功能,对函数进行拓展的形式,就称为装饰器

在执行@装饰器函数名时,就是将原函数传递到闭包中。然后,原函数的引用指向闭包返回的装饰过的内部函数的引用。

  • 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、付费专栏及课程。

余额充值