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

from dis import dis


b = 6

def f1(a):
    print(a)print(b)
    b = 9

f1(3)


print(dis(f1))  # dis模块能够查看python函数字节码

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

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))

经过高阶函数实现app

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变量也是同理

解决方案this

# 引入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

 

 

 

装饰器代码一spa

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

 

装饰器代码二code

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.0blog

相关文章
相关标签/搜索