闭包与装饰器

本文深入探讨了Python中的闭包和装饰器概念。通过示例解释了闭包如何访问外部函数变量,以及如何使用`nonlocal`关键字修改这些变量。接着,文章详细介绍了装饰器的使用,包括无参数、带参数、有返回值的函数装饰,以及如何创建万能装饰器和使用多个装饰器。此外,还讨论了装饰器参数传递和类装饰器的应用。最后,文章提到了`@property`装饰器在处理类属性中的作用。
摘要由CSDN通过智能技术生成

目录

闭包

闭包中修改外部变量

装饰器

简单应用

简化使用

装饰带有参数的函数

装饰带有返回值的函数

万能装饰器

多个装饰器

装饰器传参

   类装饰器

@property装饰器


闭包

在一个函数中访问另一个函数的内部变量,常见的形式是在一个函数中创建另一个函数,并且外部函数返回内部函数,例子如下:

test=cup("黑色")中的test=>water,函数名加上()可当做函数,这里的test("水")相当于water("水")

def cup(x):
    def water(y):
        print(x+"杯子装了"+y)
    return water
test=cup("黑色")
test("水")
黑色杯子装了水
Process finished with exit code 0

闭包中修改外部变量

使用nonlocal 声明外部变量

根据上例修改如下:

def cup(x):
    def water(y):
        nonlocal x
        x="白色"
        print(x+"杯子装了"+y)
    return water
白色杯子装了水
Process finished with exit code 0

装饰器

在不该变原有对象的基础上,给对象添加新的功能,使用了闭包

简单应用

(我们在perform函数处使用装饰器,增加了练习功能,这里函数名可作为参数传到装饰器类)

def practice(fn):
    def inner():
        print("请先练习")
        fn()
    return inner
def perform():
        print("上台表演")
perform=practice(perform)
perform()
请先练习
上台表演

简化使用

(@practice相当于perform=practice(perform))

def practice(fn):
    def inner():
        print("请先练习")
        fn()
    return inner
@practice
def perform():
        print("上台表演")
perform()

装饰带有参数的函数

(在内部函数填入对应参数即可,我在这里加了个number参数)内部函数相当于被装饰函数

def practice(fn):
    def inner(number):
        print("请先练习")
        fn(number)
    return inner
@practice
def perform(number):
        print("上台表演",number,"次")
perform(1)
请先练习
上台表演 1 次
Process finished with exit code 0

装饰带有返回值的函数

(可以将inner当做perform函数,被装饰函数有参数有返回值,那我内层函数也得有)

def practice(fn):
    def inner(number):
        print("请先练习")
        x=fn(number)
        return x
    return inner
@practice
def perform(number):
        return number
print(perform("再上台表演"))
请先练习
再上台表演
Process finished with exit code 0

万能装饰器

def decorating(fn):
    def inner(*args,**kwargs):
        fn(*args,**kwargs)
        print("简单装饰下吧")
        return fn#有返回值也可以返回
    return inner
@decorating
def decorated(*args,**kwargs):#可以传入任意数量形参
    print(args,kwargs)
decorated(1,2,user="me")
(1, 2) {'user': 'me'}
简单装饰下吧

多个装饰器

def decorating1(fn):
    def inner(*args,**kwargs):
        fn(*args,**kwargs)
        print("简单装饰下吧,这是第一个装饰器")
        return fn#有返回值也可以返回
    return inner
def decorating2(fn):
    def inner(*args,**kwargs):
        fn(*args,**kwargs)
        print("简单装饰下吧,这是第二个装饰器")
        return fn#有返回值也可以返回
    return inner
#多个装饰器的写法,函数先被最靠近他的装饰器装饰
@decorating2
@decorating1
def decorated(*args,**kwargs):#可以传入任意数量形参
    print(args,kwargs)
decorated(1,2,user="me")
(1, 2) {'user': 'me'}
简单装饰下吧,这是第一个装饰器
简单装饰下吧,这是第二个装饰器

装饰器传参

def people(peo):#装饰器传参需要在外部嵌套一个函数,和套娃相似
    def outside(fn):
        def inner(x):
            print(peo+"喝",end="")
            fn(x)
        return inner
    return outside
@people("小孩") #1、people("小孩") 2、@cup(water)
def water(x):
    print(x)
water("热水")
小孩喝热水

类装饰器

(可以理解为__call__函数将 类变得和函数一样可以调用,这个函数可以类比函数装饰器的inner方法)

class Decorating():#默认参数为object
    def __init__(self,fn):
        self.fn=fn
    def __call__(self, *args, **kwargs):#__call__方法将对象变得可以调用
        for x in range(3):
            self.fn()
@Decorating#decorate=Decorating(decorated)
def decorated():
    print("test")
decorated()
test
test
test

@property装饰器

我们可以看到调用类的私有变量需要完整的调用函数,如果使用装饰器property就可以直接使用函数名来获取私有变量,方便了许多。下面两个列子效果一样

class Test():
    def __init__(self,number):
        self._number=number
    def getage(self):
        return self._number

test=Test(1)
print(test.getage())
class Test():
    def __init__(self,number):
        self._number=number

    @property
    def getage(self):
        return self._number

test=Test(1)
print(test.getage)
1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

杜小白也想的美

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

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

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

打赏作者

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

抵扣说明:

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

余额充值