栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python闭包和装饰器

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python闭包和装饰器

知识铺垫 局部变量

1、在函数内部定义的变量称之为局部变量,在函数调用完成后,局部变量就释放掉了,因为无法在函数外部对局部变量进行调用操作,如果调用,会抛出NameError的错误

2、函数嵌套:在函数的内部又定义了一个函数,比如如下代码

# 函数嵌套
def funA():
    x = 10
    def funB():
        print(x)
    funB()
    
funA()

上图运行结果:10

通过调用funA函数,funA函数里面又调用了内嵌的funB函数

如何不通过funA()函数来调用funB()函数呢?可以在funA函数里面将funB函数进行返回,返回函数时不用加括号(函数只有在定义和调用的时候才会用到小括号)

# 函数嵌套,返回一个函数
def funA():
    x = 10
    def funB():
        print(x)
    return funB
# 方式一,通过funA()()方式进行调用
funA()()
# 方式二,将funA()赋值给一个变量,再通过该变量调用funB函数,间接的调用到了funB
# 函数内部的变量理论上在函数调用完,变量就无效了,但是现在又可以通过间接的方式调用funB
myfun = funA()
print(myfun)
myfun()

上图运行结果:

可以看到上面运行结果为:得到的是funB函数的引用

闭包

也有称之为工厂函数,就是来料加工,批量生产

# 定义一个外部函数power,然后定义内部函数,内部函数返回一个数的幂次方,外部函数返回内部函数
def power(exp):
    def exp_in(value):
        return value ** exp
    return exp_in

a = power(3)
print(a(2))   # 值为8,因为a函数是计算传入参数的3次方,这样就实现了一个计算3次方的函数,即工厂函数
b = power(4)
print(b(2))   # 置为16,因为b函数是计算传入参数的4次方,这样就实现了一个计算4次方的函数,即工厂函数

power就是工厂,由于参数不同,得到了两条产品线

装饰器

闭包的原理就是函数把函数名进行返回,那么函数能把函数名作为参数传给另外的函数吗?当然可以

演化版本一
# 演化版本一
def funa():
    print("我是funa函数。。。")

def dec(func):
    print("开始调用函数")
    funa()
    print("结束调用函数")

# 此时我想调用funa函数,但我不直接调用,我通过调用dec函数间接调用
dec(funa)

运行结果:

上面这种方式,调用funa函数,都要显式的去调用dec函数,还有更好的方式吗?有,那就是在调用funa函数的时候,它能够自觉的执行去执行dec函数,那就是使用装饰器

演化版本二:
# 演化版本二,将dec函数改为嵌套函数,并且返回值为函数引用
def dec(func):
    def call_fun():
        print("开始调用函数")
        func()
        print("结束调用函数")
    return call_fun

# 通过装饰器的语法糖,对funa函数进行装饰
@dec
def funa():
    print("我是funa函数。。。")

# 现在就可以直接调用funa函数,然后自动运行装饰器函数的代码了
funa()

运行结果与第一个版本完全一致

所以,装饰器的本质就是闭包+将函数作为参数传进去

上面装饰器的运行本质为可以拆解为

# 演化版本三(装饰器的实质调用过程),将dec函数改为嵌套函数,并且返回值为函数引用
def dec(func):
    def call_fun():
        print("开始调用函数")
        func()
        print("结束调用函数")
    return call_fun

# 这次我们不使用python语法糖
def funa():
    print("我是funa函数。。。")

# 装饰器实际的运行原理为下面
funa = dec(funa) # 将funa函数进行变换,套了一层外套函数
funa() # 再调用时就会自动执行dec函数了

多个装饰器能否用在一个函数上面呢?实际上是可以的

装饰器的调用的顺序:先里层,再外层

如何给装饰器传递参数?

在装饰器里面进行嵌套的方式,参考下图

 

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/932425.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号