• Python 变量作用域 LEGB (下)—— Enclosing function locals


    上篇:Python 变量作用域 LEGB (上)—— Local,Global,Builtin

    https://www.cnblogs.com/yvivid/p/python_LEGB_1.html

    下篇 没想到 拖这么久,距离上篇完成 都一年多了。

     

    一、闭包常规形态下的 locals作用域

     典型的闭包 如下:

    def outer(x = 3):
        def inner(y):
            print("yvivid's test")
            print("Locals =", locals())
            print("Globals =", globals())
    return x+y
    return inner

    运行结果如下:

    >>> Enclose_Func = outer(73)
    >>> Enclose_Func(10)
    yvivid's test
    Locals = {'y': 10, 'x': 73}
    Globals = {'__name__': '__main__', '__doc__': None, '__package__': None,
    '__loader__': <class '_frozen_importlib.BuiltinImporter'>,
    '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
    'outer': <function outer at 0x0000018AFDB0CD90>,
    'Enclose_Func': <function outer.<locals>.inner at 0x0000018AFB091EA0>}
    83

    可以看到,在 闭包内查看 locals() 时,可以看到 x 和 y。

    为了进一步看,x 和 y 是否变化,yvivid将代码变更为如下:

    def outer(x = 3):
        def inner(y):
            print("yvivid's test")
            print("Locals =", locals())
            print("Globals =", globals())
            print(id(x), id(y))
            return x + y
        return inner

    即,仅增加了 id 的判定。考虑到 python 数字引用机制,使用大于255的数字进行测试。

    运行结果如下:

    >>> Enclose_Func = outer(500)
    >>> Enclose_Func(322)
    yvivid's test
    Locals = {'y': 322, 'x': 500}
    Globals = {'__name__': '__main__', '__doc__': None, '__package__': None, 
    '__loader__': <class '_frozen_importlib.BuiltinImporter'>,

    '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
    'outer': <function outer at 0x0000021A09E8CD90>,
    'Enclose_Func': <function outer.<locals>.inner at 0x0000021A09E86158>} 2310858531312 2310858531600

    822
    >>> Enclose_Func(322)
    yvivid's test
    Locals = {'y': 322, 'x': 500}
    Globals = {'__name__': '__main__', '__doc__': None, '__package__': None, 
    '__loader__': <class '_frozen_importlib.BuiltinImporter'>,
    '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
    'outer': <function outer at 0x0000021A09E8CD90>,
    'Enclose_Func': <function outer.<locals>.inner at 0x0000021A09E86158>} 2310858531312 2310858531920
    822

    可以看到 运行两次,其中 id(y) 是不变更的,而 id(x) 发生了变更,因此 每次 x 是作为形参传入的。而 y 是在 Enclose_Func = outer(500) 时 确定的。

    二、闭包特殊形态下的 locals作用域

    在 Python 中 部分特殊的 闭包形式。

    1、列表推导

    >>> [ 'Locals =' + repr(locals()) for i in range(4)]
    ["Locals ={'i': 0, '.0': <range_iterator object at 0x000002C2563CE330>}",
    "Locals ={'i': 1, '.0': <range_iterator object at 0x000002C2563CE330>}",
    "Locals ={'i': 2, '.0': <range_iterator object at 0x000002C2563CE330>}",
    "Locals ={'i': 3, '.0': <range_iterator object at 0x000002C2563CE330>}"]

    >>> print("Globals =", globals())
    'Globals =', {'__name__': '__main__', '__doc__': None, '__package__': None,
    '__loader__': <class '_frozen_importlib.BuiltinImporter'>,
    '__spec__': None, '__annotations__': {},
    '__builtins__': <module 'builtins' (built-in)>}

    >>> i
    Traceback (most recent call last):
    File "<pyshell#99>", line 1, in <module>
    i
    NameError: name 'i' is not defined

    可以看到 在yvivid做的 列表推导测试中,globals() 中 是看不到 列表推导中 变量 i 的。

    这个和 for 循环有很大的不同。

    2、生成器

    yvivid_generator = ('Locals =' + repr(locals()) for i in range(4))

    3、集合推导

    yvivid_set = {'Locals =' + repr(locals()) for i in range(4)}

    -------

    A、代码 都基于 Python 3.6 环境。

    B、参考书籍 《Python学习手册(第四版)》

    【原创文档,引用请声明出处,yvivid】https://www.cnblogs.com/yvivid/p/python_LEGB_2.html

  • 相关阅读:
    C# 如何比较版本号大小
    C#中复制文件夹及文件的两种方法
    C#解压和压缩文件
    C# NPOI 导入与导出Excel文档 兼容xlsx, xls
    c#使用NPOI导出到excel
    C# 把DataGridView控件数据,转成DataTable
    C# 如何为 datagridview 中增加checkbox列
    Mixed Content: The page at 'xxx' was loaded over HTTPS, but requested an insecure resource 'xxx'.
    c# Winform DataGridView 当前单元格失去焦点的有关问题
    Docker的通俗解释
  • 原文地址:https://www.cnblogs.com/yvivid/p/python_LEGB_2.html
Copyright © 2020-2023  润新知