• 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

  • 相关阅读:
    【SQLServer】SQLServer执行计划运算符第3部分
    【SQLServer】SQLServer执行计划运算符第1部分
    【SQLServer 】SQLServer健康报告
    【MySQL】MariaDB使用connect引擎直接访问SQLServer数据库
    MySQL 报 Can't create more than max_prepared_stmt_count statements (current value: 16382)
    【MySQL】MySQL分区表
    【SQLServer】SQLServer执行计划的类型
    SQL Server日常维护常用的一些脚本整理
    数据库 SQLServer中GUID用法介绍
    sql server 性能优化方法
  • 原文地址:https://www.cnblogs.com/wuzdandz/p/10759265.html
Copyright © 2020-2023  润新知