Python 变量作用域,闭包和装饰器

时间:2023-03-09 19:31:26
Python 变量作用域,闭包和装饰器
from dis import dis

b = 6

def f1(a):
print(a)print(b)
b = 9 f1(3) print(dis(f1)) # dis模块可以查看python函数字节码

解决报错的方案一:申明b全局变量

from dis import dis

b = 6

def f1(a):
print(a)
global b
print(b)
b = 9 f1(3) print(dis(f1)) # dis模块可以查看python函数字节码

闭包

计算移动平均值

class Averager:

    def __init__(self):
self.series = [] def __call__(self, new_value):
self.series.append(new_value)
total = sum(self.series) # 汇总
return total/len(self.series) # 求平均值 avg = Averager()
print(avg(10))
print(avg(11))
print(avg(12))

通过高阶函数实现

def make_averager():
series = [] def averager(new_value):
series.append(new_value)
total = sum(series)
return total/len(series)
return averager avg = make_averager()
print(avg(10))
print(avg(11))
print(avg(12)) print(avg.__code__.co_varnames) # 打印局部变量
print(avg.__code__.co_freevars) # 打印*变量
print(avg.__closure__) # series的绑定在返回的函数的__closure__属性中
print(avg.__closure__[0].cell_contents) # 这些元素是cell对象,有个cell_contents属性,保存着真正的值 # 综上,闭包是一种函数,它会保留定义函数时存在的*变量的绑定,这样调用函数时,虽然定义作用域不可用了,但是仍能使用那些绑定 # 注意,只有嵌套在其他函数中的函数才可能需要处理不在全局作用域中的外部变量

如果是赋值操作呢?

def make_averager():
count = 0
total = 0 def averager(new_value):
count += 1
total +=new_value
return total / count
return averager
# 这里直接执行会报错,因为count += 1 相当于count = count + 1,因此当在averager的定义体内为count赋值,会把count变成局部变量。total变量也是同理

解决方案

# 引入nonlocal声明,作用是把变量标记为*变量
def make_averager():
count = 0
total = 0 def averager(new_value):
nonlocal count, total
count += 1
total += new_value
return total / count return averager

装饰器代码一

def deco(func):
def inner(*args, **kwargs):
print('this is inner')
return inner @deco
def foo():
print('this is foo') foo() # this is inner
print(foo.__name__) # inner

装饰器代码二

def wrap(func):
def deco(*args, **kwargs):
print('deco ==> ', args, kwargs)
func(*args, **kwargs)
print('this is inner')
return deco @wrap
def foo(*args, **kwargs):
print('this is foo') foo()
# deco ==> () {}
# this is foo
# this is inner print(foo.__name__) # deco

装饰器代码三

from functools import wraps

def wrap(func):
@wraps(func)
def deco(*args, **kwargs):
print('deco ==> ', args, kwargs)
func(*args, **kwargs)
print('this is inner')
return deco @wrap
def foo(*args, **kwargs):
print('this is foo') foo()
# deco ==> () {}
# this is foo
# this is inner print(foo.__name__) # foo

有空讲解0.0