python闭包和装饰器

本文探讨了Python中的闭包概念,包括其定义、构成条件及使用场景,强调了闭包在内存消耗上的特点。此外,还介绍了装饰器,一种用于给函数添加额外功能的闭包函数,它不修改原始函数代码且保持调用方式不变。文中提到了装饰器的多种应用场景及参数处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

闭包

使用场景:默认的,函数调用完成会后,销毁函数内部定义的变量,但有时候需要保存函数内的变量,再该变量的基础上进行操作

定义:在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数的引用,把这个使用外部函数变量的内部函数称为闭包。

(内函数的引用+外部函数的环境)

使用闭包时,外部函数的变量没有及时释放,会消耗内存。

闭包的构成条件:

  1. 函数嵌套
  2. 内部函数使用了外部函数的变量(参数等)
  3. 外部函数返回内部函数的引用 (引用!不是调用!)
def outer():
    a = 10

    def inner():
        b = a + 1
        print(b)
    return inner


res = outer()
print(res)
print(id(res))
print(type(res))
res()
<function outer.<locals>.inner at 0x000001BFF385F158>
1923936022872
<class 'function'>
11

闭包的使用

通过对象实现对话

class Person(object):
    def __init__(self, name):
        self.name = name

    def say(self, msg):
        print(self.name + 'Says: ' + msg)


tom = Person('tom')
jack = Person('jack')

tom.say('hi')
jack.say('what are u doing')
tom.say('watching tv')

通过函数闭包的形式实现

def Person(name):
    def Say(msg):
        print(name + ' said:' + msg)
    return Say


tom = Person('tom')
jack = Person('jack')
tom('hi')
jack('hello')
tom('bye')

 ↑ 闭包比类更加轻量,但是闭包并不能完全继承类。类有独有的继承的特性。

内函数修改外函数变量

需要通过nonlocal声明后使用

def outer():
    n = 1
    def inner():
        nonlocal n
        n = n + 10
        print(n)
    print(n)
    return inner


func = outer()
func()

装饰器

给已有函数增加额外功能的函数,本质上是一个闭包函数

特点:

  1. 不修改原有函数代码
  2. 不修改已有函数调用方式
  3. 给已有函数增加额外功能

获取函数执行时间:

def show():
    start = time.time()
    for i in range(200):
        time.sleep(0.01)
    end = time.time()
    print(f'it cose {end-start} seconds')


show()
it cose 3.175504446029663 seconds

方法二

def show():
    for i in range(200):
        time.sleep(0.01)


def count_time(func):
    start = time.time()
    func()
    end = time.time()
    print(f'it cose {end - start} seconds')
    

count_time(show)

方法三

def show():
    for i in range(200):
        time.sleep(0.01)


def count_time(func):
    def inner():
        start = time.time()
        func()
        end = time.time()
        print(f'it cost {end - start} seconds')
    return inner


# 装饰函数的原理 ----> show == inner
show = count_time(show)

show()

语法糖写法:

@count_time
def show():
    for i in range(200):
        time.sleep(0.01)

不同类型的装饰器在装饰函数的时候,需要根据被装饰的函数定义的格式适当接收参数和返回值,所以闭包中的内函数要相应接收参数和返回值。

无参数和返回值

def outer1(fun):
    def inner1():
        print('inner func')
        fun()
    return inner1


@outer1
def show1():
    print('show1')


show1()

有参数无返回值

def outer2(fun):
    def inner2(msg):
        print('inner func')
        fun(msg)
    return inner2


@outer2
def show2(msg):
    print(msg)


show2('hi')

无参数有返回值

def outer3(fun):
    def inner3():
        print('inner func')
        res = fun()
        return res
    return inner3


@outer3
def show3():
    return 'hi show3'

print(show3())

有参数有返回值

def outer4(fun):
    def inner4(msg):
        print('inner func')
        res = fun(msg)
        return res
    return inner4


@outer4
def show4(msg):
    return 'hi ' + msg

print(show4('you'))

不定参数

def outer(func):
    def inner(*args, **kwargs):
        res = func(*args, **kwargs)
        return res
    return inner

多个装饰器使用

——————睡觉了 周末再看吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值