一、闭包
1.简单演示
条件
在函数嵌套(函数里面在定义函数)的前提下
内部函数使用了外部函数的变量(还包括外部函数的参数)
外部函数返回了内部函数
def outer(): n = 1 #内部定义 def inner(): #使用外部变量 print(n) #返回内部函数 return inner ret = outer() print(ret)
def Person(name): def say(msg): print(name+"Say: "+msg) return say tom = Person('tom') jack = Person('jack') tom('你好') jack('早上好')
2.内函数修改外函数变量问题
真常来说内部函数只有对外部函数访问的权利
def outer(): n = 1 def inner(): n += 10 print(n) print(n) return inner func = outer() func()
需要修饰符
def outer(): n = 1 def inner(): nonlocal n n += 10 print(n) print(n) return inner func = outer() func()
需要用nolocal
二、装饰器
1.基础使用
特点:
不修改已有函数的源代码
不修改已有函数的调用方法
给已有函数增加额外的功能
他的本质就是一个闭包函数
我们编辑一个计算函数用时功能的程序
import time def for1(): for i in range(10000000): i +=1 print(i) def start(func): def inner(): s = time.time() func() e = time.time() print("用时: ",e-s) return inner func = start(for1) func()
用装饰器来写
import time def start(func): def inner(): s = time.time() func() e = time.time() print("用时: ",e-s) return inner @start def for1(): for i in range(10000000): i +=1 print(i) for1()
由此可见装饰器就是一种语法糖
注意:装饰器这里一定要有参数
2.通用装饰器
参数问题
import time def start(func): def inner(): s = time.time() func() e = time.time() print("用时: ",e-s) return inner @start def for1(a): for i in range(a): i +=1 print(i) for1(10000000000000000)
总结一下可能有的四种状态
#无参数,无返回值 def outer1(func): def inner(): print("装饰1.。。") func() print("装饰2.。。") return inner @outer1 def show1(): print("show1....") show1() print("________________________") # 有参数,无返回值 def outer2(func): def inner(msg): print("装饰1.。。") func(msg) print("装饰2.。。") return inner @outer2 def show2(msg): print("show2....",msg) show2("python") print("________________________") # 无参数,有返回值 def outer3(func): def inner(): print("装饰1.。。") ret = func() print("装饰2.。。") return ret return inner @outer3 def show3(): return "shoe3....." print(show3()+"Nihao") print("________________________") # 有参数,有返回值 def outer4(func): def inner(msg): print("装饰1.。。") ret = func(msg) print("装饰2.。。") return ret return inner @outer4 def show4(msg): return "shoe3....." +msg print(show4("python4 ")+"Nihao")
我们需要一个通用的修饰器
def outer(func): def inner(*args,**kwargs): print("装饰1.。。") ret = func(*args,**kwargs) print("装饰2.。。") return ret return inner #无参数,无返回值 @outer def show1(): print("show1....") show1() print("________________________") # 有参数,无返回值 @outer def show2(msg): print("show2....",msg) show2("python") print("________________________") # 无参数,有返回值 @outer def show3(): return "shoe3....." print(show3()+"Nihao") print("________________________") # 有参数,有返回值 @outer def show4(msg): return "shoe3....." +msg print(show4("python4 ")+"Nihao")
3.多个修饰器引用
def wrapper_div(func): def inner(*args,**kwargs): return "<div>" + func(*args,**kwargs) + '</div>' return inner def wrapper_p(func): def inner(*args,**kwargs): return "<p>" + func(*args,**kwargs) + '</p>' return inner @wrapper_p @wrapper_div def show(): return "show inner " print(show())
执行流程
4.装饰器传参
需要多层函数嵌套来完成
def set_a(msg): def set_f(func): def inner(): print("装饰内容: "+msg) func() return inner return set_f @set_a("你好") def show(): print("show....") show()
三、类装饰器
1.callable()和__call__
def show(): print("show") #这个函数用来测试参数是否是可以调用对象 print(callable(show)) print(callable(1)) print(callable("aa")) class P(): #当一个类中实现了__call__函数 #那么这个类的实例对象就变成了可调用对象,也就是说,实例对象后面可以加() def __call__(self, *args, **kwargs): print("Call run") tom = P() print(callable(tom)) tom()
其实也就是说,类本来是不可调用的对象,但是装饰器需要是可调用对象,所以只需要了解这点我们就可以使用了
2.类装饰器的简单使用
class Wra(): def __init__(self,func): self.func = func def __call__(self, *args, **kwargs): print("装饰") self.func() @Wra def show(): print("show...") show()
结语
这是最后几篇了,接下来更新Linux云计算方面的博客,大家👍啊!