一、名称空间:存放变量名与对应值绑定关系的地方。
分为三种:locals(),是函数内的名称空间,包含局部变量与形参;globals():全局变量,函数定义所在模块的名字空间;builtins():内置模块的名字空间。
level = 'l0' n = 22 def func(): level = 'l1' n = 33 print(locals()) def outer(): n = 44 level = 'l2' print(locals(),n) def inner(): level = 'l3' print(locals(),n) inner() outer() func() #打印 func()/outer()/inner() {'level': 'l1', 'n': 33} {'level': 'l2', 'n': 44} 44 {'level': 'l3', 'n': 44} 44
#名称空间查找顺序:局部名称空间--->全局名称空间--->内置名称空间
不同变量的作用域不同是由这个变量所在的命名空间决定的。
作用域即范围:全局范围:全局存活,全局有效;局部范围:临时存活,局部有效。
#1、作用域即范围 - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效 - 局部范围(局部名称空间属于该范围):临时存活,局部有效 #2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下 x=1 def f1(): def f2(): print(x) return f2 x=100 def f3(func): x=2 func() x=10000 f3(f1()) #3、查看作用域:globals(),locals() LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__ locals 是函数内的名字空间,包括局部变量和形参 enclosing 外部嵌套函数的名字空间(闭包中常见) globals 全局变量,函数定义所在模块的名字空间 builtins 内置模块的名字空间
二、闭包
定义:内部函数包含对外部作用域,而非全局作用域的引用。之前我们都是通过参数将值传给函数,闭包给我们提供了一种新的方式。
outer(): name='alex' def inner(): print("在inner里面打印外层函数的变量", name) return inner f = outer() f()
闭包的意义:
返回的函数对象,不仅仅是一个函数对象,在该函数外层还包裹着一层作用域,这使得函数无论在何处调用,都优先使用自己外层包裹的作用域。应用:延迟计算。
def counter():
n = 0
def incr():
nonlocal n
x = n
n += 1
return x
return incr
c = counter()
print(c())
print(c())
print(c())
print(c.__closure__[0].cell_contents) # 查看闭包的元
三、装饰器
定义:装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方法。
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
开放封闭原则:对修改封闭,对拓展开放
装饰器就是闭包的一种应用场景
装饰器的使用:
1、无参数的使用
import time def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper @timmer def foo(): time.sleep(3) print('from foo') foo()
2、有参数的使用
def auth(driver='file'): def auth2(func): def wrapper(*args,**kwargs): name=input("user: ") pwd=input("pwd: ") if driver == 'file': if name == 'egon' and pwd == '123': print('login successful') res=func(*args,**kwargs) return res elif driver == 'ldap': print('ldap') return wrapper return auth2 @auth(driver='file') def foo(name): print(name) foo('egon')