作用域、闭包、装饰器
作用域
程序创建, 访问, 改变一个变量时, 都是在一个保存该变量的空间内进行, 这个空间被称为命名空间, 即作用域
-
Built-in
内置- 可以在Python环境中的任何模块, 任意位置访问和调用
-
Global
全局变量-
只作用于当前模块(可以理解为当前文件)
-
可以简单地理解为定以在函数外的变量就是全局变量, 如果在函数体定义那就时局部变量.
-
如何将局部变量变成全局变量?
-
使用
global
关键字a = 1 def foo(): global a a = 2 print(a) foo() print(a)
-
-
-
Enclosed(嵌套)
自由变量在嵌套函数中, 访问函数体之外的非全局变量
-
只作用于嵌套函数体
-
最大的应用就是闭包
-
自由变量是个相对的概念
-
将局部变量变成自由变量
-
使用
nonlocal
关键字def make_averager(): total = 0 count = 0 def averager(value): nonlocal total, count total += value count += 1 return total / count return averager my_avg = make_averager() print(my_avg(1)) print(my_avg(2))
-
-
-
Local
局部变量-
只作用于当前函数体
-
一旦变量在函数体中赋值, 那么该变量相对该函数来说就是局部变量
a = 1 b = [] def foo(): a = 2 b.append(2) # 局部变量会在函数声明的时候就定义好 # 不是按照我们逻辑思维上先执行全局变量b.append(2), 然后再声明一个局部变量b # 而是再函数声明之初就已经定义了b为局部变量 # b = 3 return None foo() print(a) print(b)
-
闭包和装饰器
-
闭包
闭包指延申了作用域的函数, 也就是作用域中的
Enclosed
的概念def make_averager(): series = [] def averager(value): series.append(value) total = sum(series) return total / len(series) return averager # my_avg就是延申了作用域的函数 # series就是被延申作用域的变量 my_avg = make_averager() print(my_avg(1)) print(my_avg(2))
-
装饰器
-
实现原理
就是闭包, 延申了被装饰函数的作用域, 本质是将函数作为参数传递给一个可调用对象(函数或类)
-
目的
增加和扩展可调用对象(函数或类)的行为
-
实现一个装饰器
-
通过
@
关键字装饰函数def clock_it_deco(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"{func.__name__} execute time: {format(end_time - start_time, '.2f')} s") return result return wrapper # @other_deco @clock_it_deco def foo(a, b): count = 1 while True: if count > a ** b: break count += 1 foo(10, 5)
-
等同于
foo = clock_it_deco(foo) foo(10, 5)
-
-