闭包函数与装饰器

Posted 云烟成雨。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了闭包函数与装饰器相关的知识,希望对你有一定的参考价值。

闭包函数

定义

  在函数内定义了一个内部函数,该内部函数只对外部作用域变量的引用,不对全局作用域变量的引用的函数被成为闭包函数。

代码示例

1 def foo():
2     fun = "我是外部变量"
3     def bar(): # 指的是bar函数为闭包函数,而不是foo()函数为闭包函数
4         print(fun)
5     return bar
6 
7 fun = "干扰测试" # 这里的fun是全局变量,但是执行a函数,打印的结果始终是bar函数的外部变量 fun。
8 a = foo()
9 a()

装饰器

定义

  装饰函数的工具(函数)

特点

  在不改变被装饰函数的源代码和调用方式的前提下,为被装饰的函数增加新的功能。

装饰器的基本格式

 1 def foo(fun): #foo为装饰器名字,fun为被装饰函数的名字
 2     def run(*args,**kwargs): #使用不定长参数可以解决被装饰函数有五参数的问题
 3         pass
 4         ret = fun(*args,**kwargs)#如何定义的就如何执行。有的被装饰函数有返回,因此要把运行被装饰函数的返回值保存下来
 5         pass
 6         return ret #返回运行被装饰函数的返回值,代码结束。
 7     return run
 8 # @foo3 
 9 # @foo2
10 @foo  #一个函数可以被多个装饰器装饰,最下面的装饰起会最先被运行,越往上就靠后执行
11 def test1(): # 被装饰函数无形参,无返回值类型
12     pass
13 
14 
15 @foo
16 def test2(a): # 被装饰函数有形参类型
17     print(a)
18     pass
19 
20 
21 @foo
22 def test3(a): # 被装饰函数有形参有返回值类型
23     pass
24     return a
25 
26 
27 @foo
28 def test4(a,b,c,d): # 被装饰函数有多个形参类型
29     pass

无參装饰器

  特点:@装饰器名字后面没有括号,只需传入被装饰函数的名字,无需传入其他的参数的装饰起被成为无參装饰器。

代码示例

def foo(fun):
    def bar(*args,**kwargs):
        print("这是前奏")
        ret = fun(*args,**kwargs)
        print("这是结尾")
        return ret
    return bar

@foo # 实际上是执行了 "index = foo(index)",这一步的最终结果是把bar的内存地址赋值给index变量,这样以后只要执行index(),实际上去执行bar()。
def index():
    print("我是index页面")

# index = foo(index)
index()

装饰器的实质

  装饰器对被装饰函数功能添加的实质是把被装饰函数的内存地址替换为另一个函数的内存地址,以后只要执行装饰函数的函数()名实际上执行替换过函数的地址。而装饰器函数内部一方面执行了原来被装饰函数的函数体,同时也新添加了部分代码,从而实现了对被装饰函数功能的添加。

有参装饰器

  特点:在@装饰器名后面有(形参),要满足在传入被装饰函数内存地址的同时,还需要传入一个变量。

def timer2(auth_type): #1:什么也不做
    def timer(fun):
        def bar(*arg, **kwargs):
            if auth_type == "file":
                name = input("name:")
                pwd = input("pwd:")
                if name == "root" and pwd == "admin":
                    ret = fun(*arg, **kwargs)
                    return ret
                else:
                    print("滚去登录")
            else:
                print("还不会玩")
        return bar
    return timer

@timer2(auth_type="file") #只要有了(),就是一个函数,首先执行的就是timer2()这个函数,此时执行的结果为@timer,同时拿到了一个auth_type="file"的变量,然后再去执行 ---->index = timer(index) #发现要去执行timer2函数
def index():
    # time.sleep(random.randrange(1,3))
    print("这里是index页面")
index()


@timer2(auth_type="file")
def foo(a,b):
    print(a,b)
foo(1,2)


@timer2(auth_type="file")
def boo(a):
    print(a)

boo(456)

 

以上是关于闭包函数与装饰器的主要内容,如果未能解决你的问题,请参考以下文章

python11 装饰器与闭包

闭包与装饰器

闭包函数与装饰器

python 闭包与装饰器

闭包函数,装饰器

python3命名空间与作用域,闭包函数,装饰器