python之函数的进阶闭包装饰器
Posted 独孤。。。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之函数的进阶闭包装饰器相关的知识,希望对你有一定的参考价值。
本节内容:函数的进阶、闭包、装饰器
1.名称空间
2.作用域
3.取值顺序
4.函数的嵌套
5.内置函数
6.关键字
7.函数的应用
8.闭包
9.装饰器
1、名称空间
1.1 名称空间
当程序运行时,代码从上之下一次执行,他会将变量与值的关系存储在一个空间中,这个空间叫做名称空间,命名空间,全局名称空间。
1.2 局部名称空间
当程序遇到函数时,他会将函数名存在内存中,函数体莫不关心。
当函数执行时,内存会临时开辟一个空间,存放函数体里面的代码(变量,代码等),
函数外面访问不到临时空间的内容,随着函数的执行完毕,临时名称空间会释放掉,
向这个临时开辟的空间叫临时名称空间,也叫局部名称空间。
1.3 Python中名称空间种类
内置名称空间。
全局名称空间。
局部名称空间。
2、作用域
2.1 全局作用域
内置名称空间
全局名称空间
2.2 局部作用域
局部名称空间
2.3 加载顺序
内置名称空间 ---> 全局名称空间(当程序执行时) ---> 局部名称空间(当函数调用时)
3、取值顺序
取值顺序:单向不可逆
局部名称空间(当函数调用时) -->全局名称空间(当程序执行时) -->内置名称空间
3.1 先从局部找
name1 = \'oldboy\' def func2(): name1 = \'alex\' print(name1) func2() =====>输出 alex
3.2 再从全局找
name1 = \'oldboy\' def func2(): print(name1) func2() =====>输出 oldboy
3.3 最后从内置空间找
def func2(): print(input) func2() =====>输出 <build-in function input>
def func1(): print(666) def func2(): func1() print(333) def func3(): func2() print(222) print(111) func3() print(555) =====>输出 111 666 333 222 555 ========== def func1(): name = \'alex\' print(name) def func2(): name1 = \'太白\' print(333) print(444) func2() func1() =====>输出 alex 444 333
5、内置函数
5.1 globals()
返回一个字典,字典里面的内容是全局作用域的内容。
name = \'alex\' age = 1000 sex = \'男\' def func1(): name1 = \'oldboy\' age = 10000 func1() print(globals()) print(locals()) =========>输出 None, \'name\': \'alex\', \'age\': 1000, \'sex\': \'男\', \'func1\': <function func1 at 0x0000000001CF2E18>} None, \'name\': \'alex\', \'age\': 1000, \'sex\': \'男\', \'func1\': <function func1 at 0x0000000001CF2E18>}
5.2 locals()
返回一个字典,当前位置 的所有变量。
def func1(): name1 = \'oldboy\' age = 10000 def func2(): name2 = \'wusir\' age2 = 25 print(globals()) print(locals()) func2() func1() =====>输出 None, \'func1\': <function func1 at 0x0000000001D02E18>} {\'age2\': 25, \'name2\': \'wusir\'}
6、关键字
6.1 global
6.1.1 引用并改变一个全局变量
count = 1 def func1(): global count count = count + 1 # count = count + 100 print(count) func1() print(count) =====>输出 2 2
6.1.2 在局部作用域声明一个全局变量
def func1(): global name name = \'alex\' print(name) func1() print(name) =====>输出 alex alex
6.2 nonlocal
1、不能操作全局变量
从哪层引用的该变量,从那层开始全部改变。
def func1(): count = 1 def inner(): nonlocal count count = count + 3 print(count) def inner2(): pass inner() print(count) func1() =====>输出 4 4
list = [] def func1(): list.append(666) func1() print(list) =====>输出 [666]
3、如果默认参数是一个可变的数据类型,那么他在内存中永远是一个
def extendList(val,list=[]): list.append(val) return list list1 = extendList(10) print(\'list1=%s\'%list1) list2 = extendList(123,[]) print(\'list2=%s\'%list2) list3 = extendList(\'a\') print(\'list3=%s\'%list3) print(\'list1=%s\'%list1) print(\'list2=%s\'%list2) print(\'list3=%s\'%list3) =======>输出 list1=[10] list2=[123] list3=[10, \'a\'] list1=[10, \'a\'] list2=[123] list3=[10, \'a\']
7、函数名的应用
def func1(): print(666) 1 打印函数名 print(func1) # <function func1 at 0x000000000258F9D8> 2 函数名可以作为容器类数据的元素 def func1(): print(111) def func2(): print(222) def func3(): print(333) l1 = [func1, func2, func3] for i in l1: i() 3 函数名可以作为函数的参数 def func1(): print(111) def func2(x): print(x) x() print(222) func2(func1) 4 函数名可以作为函数的返回值 def func1(): return 111 def func2(x): # x = func1 print(222) return x ret = func2(func1) # func1 print(ret()) print(ret)
7.1 第一类对象
def func3(x): print(x) return x def func1(): print(1111) return 111 f1 = func1 f2 = f1 f3 = f2 print(f3) f3() =========>输出 <function func1 at 0x00000000025120D0> 1111
8、闭包
内层函数对外层函数非全局变量的引用,就叫做闭包。
def wrapper(): name = \'alex\' def inner(): print(name) inner() wrapper() ======>输出 alex ======= name = \'alex\' def wrapper(): def inner(): print(name) inner() print(inner.__closure__) # None wrapper() =======>输出 alex None
8.1 通过函数名.__closure__
name = \'alex\' def wrapper(x): x = name def inner(): print(x) inner() print(inner.__closure__) wrapper(name) =====>输出 alex (<cell at 0x0000000001E16498: str object at 0x000000000049C110>,)
import time print(time.time()) def func1(): time.sleep(0.3) print(\'非常复杂......\') start_time = time.time() func1() end_time = time.time() print(\'此函数的执行效率%s\' %(end_time-start_time)) ===========>输出 1527471870.8405445 非常复杂...... 此函数的执行效率0.3000171184539795 ============== # 改版1:我要封装到一个函数中 import time print(time.time()) def func1(): time.sleep(0.3) print(\'非常复杂......\') def func2(): time.sleep(0.3) print(\'特别复杂......\') func1() func2() ========>输出 1527471978.33138 非常复杂...... 特别复杂...... ============== # 改版2:被测试函数当参数传入,可以测试多个函数的执行效率 def timmer(f): start_time = time.time() f() end_time = time.time() print(\'此函数的执行效率%s\' %(end_time-start_time)) timmer(func1) timmer(func2) ================= 改版3::测试函数执行效率的同时,不要改变原函数的调用方式。 def func1(): time.sleep(0.3) print(\'非常复杂......\') def func2(): time.sleep(0.3) print(\'特别复杂......\') # func1() # func2() def timmer(f): start_time = time.time() f() end_time = time.time() print(\'此函数的执行效率%s\' % (end_time - start_time)) f1 = func1 func1 = timmer # func1(f1) # timmer(func1) ================= 改版4::改版3虽然大体上满足了我的要求,但是增加两行代码, 而且多了参数,不好,继续改,尽量不添加其他代码,而且做到调用时一模一样 最简单的装饰器。 def func1(): time.sleep(0.3) print(\'非常复杂......\') def func2(): time.sleep(0.3) print(\'特别复杂......\') # func1() # func2() def timmer(f): # f = func1 函数名 def inner(): start_time = time.time() f() end_time = time.time() print(\'此函数的执行效率%s\' % (end_time - start_time)) return inner func1 = timmer(func1) # inner func2 = timmer(func2) # inner func1() # inner() func2() ======================== 改版5::改版4每次测试一个函数的执行效率时,都需要加一行 func1 = timmer(func1)代码,麻烦 python提出了一个语法糖 @。 def timmer(f): # f = func1 函数名 def inner(): start_time = time.time() f() end_time = time.time() print(\'此函数的执行效率%s\' % (end_time - start_time)) return inner @timmer # func1 = timmer(func1) inner def func1(): time.sleep(0.3) print(\'非常复杂......\') func1() # inner() ======================== 改版6:被装饰的函数肯定要有参数的,你现在不能满足,解决这个问题。 被装饰的函数带参数的装饰器 def timmer(f): # f = func1 函数名 def inner(*args,**kwargs): # args = (1,2),kwargs {sex:\'nv\',name:\'alex\'} start_time = time.time() f(*args,**kwargs) # f(1,2,,sex=\'nv\',name=\'alex\') end_time = time.time() print(\'此函数的执行效率%s\' % (end_time - start_time)) return inner @timmer # func1 = timmer(func1) inner def func1(a,b): time.sleep(0.3) print(a,b) print(\'非常复杂......\') @timmer # func1 = timmer(func1) inner def func2(a,b,name,sex=\'man\'): # f(1,2,,sex=\'nv\',name=\'alex\') time.sleep(0.3) print(a,b,sex,name) print(\'非常复杂......\') func2(1,2,sex=\'nv\',name=\'alex\') # inner() ==================== 改版7:被装饰的函数肯定要有返回值的,解决这个问题。 被装饰的函数带参数且有返回值的装饰器 def timmer(f): # f = func2 函数名 def inner(*args,**kwargs): # args = (1,2),kwargs {sex:\'nv\',name:\'alex\'} start_time = time.time() ret = f(*args,**kwargs) # f(1,2,,sex=\'nv\',name=\'alex\') end_time = time.time() print(\'此函数的执行效率%s\' % (end_time - start_time)) return ret return inner @timmer # func1 = timmer(func1) inner def func2(a,b,name,sex=\'man\'): # f(1,2,,sex=\'nv\',name=\'alex\') time.sleep(0.3) print(a,b,sex,name) print(\'非常复杂......\') return 666 print(func2(1,2,sex=\'nv\',name=\'alex\')) # inner() def timmer(f): def inner(*args,**kwargs): start_time = time.time() ret = f(*args,**kwargs) end_time = time.time() print(\'此函数的执行效率%s\' % (end_time - start_time)) return ret return inner @timmer def func2(a,b,name,sex=\'man\'): time.sleep(0.3) print(a,b,sex,name) print(\'非常复杂......\') return 666 ret1 = func2(1,2,sex=\'nv\',name=\'alex\') print(ret1) def wrapper(f): def inner(*args,**kwargs): """被装饰函数执行之前的操作""" ret = f(*args,**kwargs) """被装饰函数执行之后的操作""" return ret return inner
以上是关于python之函数的进阶闭包装饰器的主要内容,如果未能解决你的问题,请参考以下文章