python - 无法在 Python 3 的列表理解中使用 locals() 吗?

标签 python python-3.x scope list-comprehension scoping

下面的代码适用于 Python 2,但不适用于 Python 3。有没有办法在 Python 3 中访问局部变量?或者这些情况的替代解决方案?

[('{name_var}_{i:02d}of{maxpg:02d}.{date_var}').format(i, **locals()) 
  for i in range(start, end)]

Python 3 中的错误:

KeyError: 'local_var'

下面是上面的一个更简单的玩具示例(适用于 Python 2,但不适用于 3)

local_var = 'hello'
['{local_var}'.format(**locals()) for i in range(1)]

Python 3 中的错误:

KeyError: 'local_var'

最佳答案

正如 @user2357112 在评论中所解释的,列表推导式在 Python 3 中具有自己的本地作用域(因此 locals() dict)。

比较:

>>> var=1
>>> [locals() for _ in range(1)]
[{'_': 0, '.0': <range_iterator object at 0x7f5b65cb7270>}]

>>> [l for l in (locals(), )]
[{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'var': 1}]

在第一种情况下,函数 locals 在列表理解代码内调用,而在第二种情况下,函数调用的结果作为参数传递给列表理解。

dis 模块确认:

>>> from dis import dis
>>> def f(): return [locals() for _ in range(1)]
... 
>>> dis(f)
  1           0 LOAD_CONST               1 (<code object <listcomp> at 0x7fc8173bd9c0, file "<stdin>", line 1>)
              2 LOAD_CONST               2 ('f.<locals>.<listcomp>')
              4 MAKE_FUNCTION            0
              6 LOAD_GLOBAL              0 (range)
              8 LOAD_CONST               3 (1)
             10 CALL_FUNCTION            1
             12 GET_ITER
             14 CALL_FUNCTION            1
             16 RETURN_VALUE

未调用 locals 函数。您可以在列表理解的代码中看到调用:

>>> dis(f.__code__.co_consts[1])
  1           0 BUILD_LIST               0
              2 LOAD_FAST                0 (.0)
        >>    4 FOR_ITER                10 (to 16)
              6 STORE_FAST               1 (_)
              8 LOAD_GLOBAL              0 (locals)
             10 CALL_FUNCTION            0
             12 LIST_APPEND              2
             14 JUMP_ABSOLUTE            4
        >>   16 RETURN_VALUE

同时

>>> def g(): return [l for l in (locals(),)]
... 
>>> dis(g)
  1           0 LOAD_CONST               1 (<code object <listcomp> at 0x7f5b65cb8930, file "<stdin>", line 1>)
              2 LOAD_CONST               2 ('g.<locals>.<listcomp>')
              4 MAKE_FUNCTION            0
              6 LOAD_GLOBAL              0 (locals)
              8 CALL_FUNCTION            0
             10 BUILD_TUPLE              1
             12 GET_ITER
             14 CALL_FUNCTION            1
             16 RETURN_VALUE

在列表理解执行之前调用locals函数,构建iter并将其传递给列表理解。

关于您的具体问题,您可以在列表理解之外强制对 locals 求值(请注意 i=i:这不是位置参数):

>>> d = locals()
>>> ['{name_var}_{i:02d}of{maxpg:02d}.{date_var}'.format(i=i, **d) for i in range(start, end)]
['VAR_00of01.2019-01-01', 'VAR_01of01.2019-01-01', 'VAR_02of01.2019-01-01', 'VAR_03of01.2019-01-01', 'VAR_04of01.2019-01-01', 'VAR_05of01.2019-01-01', 'VAR_06of01.2019-01-01', 'VAR_07of01.2019-01-01', 'VAR_08of01.2019-01-01', 'VAR_09of01.2019-01-01']

如果您的Python版本是3.6或更高版本,您可以使用(f strings)[ https://docs.python.org/3/whatsnew/3.6.html#pep-498-formatted-string-literals]

>>> [f'{name_var}_{i:02d}of{maxpg:02d}.{date_var}' for i in range(start, end)]
['VAR_00of01.2019-01-01', 'VAR_01of01.2019-01-01', 'VAR_02of01.2019-01-01', 'VAR_03of01.2019-01-01', 'VAR_04of01.2019-01-01', 'VAR_05of01.2019-01-01', 'VAR_06of01.2019-01-01', 'VAR_07of01.2019-01-01', 'VAR_08of01.2019-01-01', 'VAR_09of01.2019-01-01']

但是,我认为每次迭代都在 locals() 中进行查找并不是一个好主意。您可以构建一次 format_string 并在列表理解中使用它:

>>> format_string = '{name_var}_{{i:02d}}of{maxpg:02d}.{date_var}'.format(**locals()) 
>>> format_string
'VAR_{i:02d}of01.2019-01-01'

或者(>= 3.6):

>>> format_string = f'{name_var}_{{i:02d}}of{maxpg:02d}.{date_var}'

那么你有:

>>> [format_string.format(i=i) for i in range(start, end)]
['VAR_00of01.2019-01-01', 'VAR_01of01.2019-01-01', 'VAR_02of01.2019-01-01', 'VAR_03of01.2019-01-01', 'VAR_04of01.2019-01-01', 'VAR_05of01.2019-01-01', 'VAR_06of01.2019-01-01', 'VAR_07of01.2019-01-01', 'VAR_08of01.2019-01-01', 'VAR_09of01.2019-01-01']

关于python - 无法在 Python 3 的列表理解中使用 locals() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55084171/

相关文章:

python - Pywinauto type_keys() 省略字符串中的 "%"

xml-parsing - Python 3 的 SGML 解析器?

c++ - 我可以修改作为参数传递的指针的目标吗?

scope - Google 驱动器 API 范围 : https://www. googleapis.com/auth/drive

python - 如何根据列标签获取数据框的交集?

python - 是否有解决方法可以在单独的线程中清空事件队列?

python - 多人游戏中的Pygame和socket : OverflowError

javascript - 应该在 jQuery 文档内部或外部编写和调用 Javascript 函数吗?

python - 为什么我没有获得 Dialogflow 指定的 RAW API RESPONSE 响应?

python - 如何使用函数将字典的值添加到Python中