【问题标题】:How are variables looked up in Python?如何在 Python 中查找变量?
【发布时间】:2018-02-18 23:01:37
【问题描述】:

我一直在用 Python 进行试验,并观察到一些我不理解的行为。

我认为执行查找时会发生什么:

  1. 检查当前帧中的局部变量
  2. 如果未找到变量,请尝试第一个外框
  3. 重复 1 和 2 直到没有更多的外框,如果没有找到变量,则抛出 NameError

这与print(x) 的第一次调用一致,因为我已将x 强制放入第一个外框。

但是,print(x) 的第二次调用失败并返回 NameError,这让我感到困惑,因为 x 存在于局部变量中。

谢谢!

import inspect

def test():

    frame_inner = inspect.currentframe()
    print(locals())  # { 'frame_inner': A }

    frame_outer = inspect.getouterframes(frame_inner)[1].frame
    y = 'y'

    frame_outer.f_locals['x'] = 'x'

    print(locals()) # { 'frame_inner': A, 'frame_outer': B, 'y': 'y' }
    print(y)        # y
    print(x)        # x

    del frame_outer.f_locals['x']

    frame_inner.f_locals['x'] = 'x'

    print(locals()) # { 'frame_inner': A, 'frame_outer': B, 'y': 'y', 'x': 'x' }
    print(y)        # y
    print(x)        # NameError: name 'x' is not defined


test()

【问题讨论】:

  • 您会感到困惑,因为您正在修改f_locals。这基本上是未定义的行为。
  • 修改locals() 返回的dict不会影响解释器看到的局部变量。见这里:docs.python.org/3/library/functions.html#locals
  • @juanpa.arrivillaga 此代码不会修改locals() 的返回值。它确实修改了框架的f_locals,但这也可能不是一个好主意。
  • @viraptor locals 返回 frame.f_locals(至少在 cpython 中)。

标签: python python-3.x python-internals


【解决方案1】:

如果您查看https://docs.python.org/3/library/inspect.html,您会发现所有官方用法都是用于...检查值。

inspect 模块提供了几个有用的函数来帮助获取有关活动对象的信息,例如模块、类、方法、函数、回溯、框架对象和代码对象。

没有描述修改的安全性,您可以假设如果您想修改从该模块获得的框架或其他东西,您只能靠自己。您所做的任何更改都不能保证传播回当前状态的内部表示。

【讨论】:

  • 谢谢 作为进一步说明,我尝试从函数中调用test(),但两个调用都失败了。所以看起来检查能够影响全局框架而不是局部框架的变化,这导致我的困惑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
  • 2011-04-13
  • 2018-02-21
相关资源
最近更新 更多