闭包函数
定义
在函数内定义了一个内部函数,该内部函数只对外部作用域变量的引用,不对全局作用域变量的引用的函数被成为闭包函数。
代码示例
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)