【问题标题】:variables in list comprehension test are seen as not defined in an exec with python3列表理解测试中的变量被视为未在 python3 的 exec 中定义
【发布时间】:2023-03-05 10:33:01
【问题描述】:

首先,请注意,它不像其他关于 exec 内部变量的 SO 问题。这是一个在 exec 中的列表理解 TEST 中使用的变量的问题。

拿这个 test.py :

myglob_var = 'my global var'

def myfunc():
    s = """
print('myglob_var =',myglob_var)
users = ['root','service']
flag = True
c_list = [ u for u in users ]
print('list comprehension =',c_list)
c_list_with_test = [ u for u in users if flag ]
print('list comprehension with test =',c_list_with_test)
some_result = 'a result'
"""
    exec(s)

myfunc()

执行时我有这个:

$ python3 test.py
myglob_var = my global var
list comprehension = ['root', 'service']
Traceback (most recent call last):
  File "test.py", line 18, in <module>
    myfunc()
  File "test.py", line 15, in myfunc
    exec(s)
  File "<string>", line 7, in <module>
  File "<string>", line 7, in <listcomp>
NameError: name 'flag' is not defined

usersflag 都在 exec() 中定义。两者都用于列表理解。但只有 flag 被视为未定义,因为它在测试中使用。

我可以使用exec(s,globals()) 解决这个问题:

myglob_var = 'my global var'

def myfunc():
    s = """
print('myglob_var =',myglob_var)
users = ['root','service']
flag = True
c_list = [ u for u in users ]
print('list comprehension =',c_list)
c_list_with_test = [ u for u in users if flag ]
print('list comprehension with test =',c_list_with_test)
some_result = 'a result'
"""
    exec(s, globals())
    print('some_result as global var =',globals().get('some_result'))
    print('some_result as local var =',locals().get('some_result'))

myfunc()

执行时我得到:

$ python3 test.py
myglob_var = my global var
list comprehension = ['root', 'service']
list comprehension with test = ['root', 'service']
some_result as global var = a result
some_result as local var = None

一切都很好,除了我希望 some_result 是本地的而不是全局的。

为此,我使用了 SO 上另一个问题的配方:

myglob_var = 'my global var'

def myfunc():
    s = """
print('myglob_var =',myglob_var)
users = ['root','service']
flag = True
c_list = [ u for u in users ]
print('list comprehension =',c_list)
c_list_with_test = [ u for u in users if flag ]
print('list comprehension with test =',c_list_with_test)
some_result = 'a result'
"""
    nm = {}
    exec(s, globals(), nm)
    print('Result =',nm.get('some_result'))

myfunc()

flag 上的未定义再次出现:

$ python3 test.py
myglob_var = my global var
list comprehension = ['root', 'service']
Traceback (most recent call last):
  File "test.py", line 18, in <module>
    myfunc()
  File "test.py", line 15, in myfunc
    exec(s, globals(), nm)
  File "<string>", line 7, in <module>
  File "<string>", line 7, in <listcomp>
NameError: name 'flag' is not defined

编辑:

我可以这样解决:

myglob_var = 'my global var'

def myfunc():
    s = """
print('myglob_var =',myglob_var)
users = ['root','service']
flag = True
c_list = [ u for u in users ]
print('list comprehension =',c_list)
c_list_with_test = [ u for u in users if flag ]
print('list comprehension with test =',c_list_with_test)
some_result = 'a result'
"""
    nm = globals().copy()
    exec(s, nm)
    print('Result =',nm.get('some_result'))

myfunc()

我明白了:

myglob_var = my global var
list comprehension = ['root', 'service']
list comprehension with test = ['root', 'service']
Result = a result

看起来不错,只是在我的实际应用程序中,变量分配在 exec 之前:

myglob_var = 'my global var'

def myfunc():
    flag = True
    users = ['root','service']
    s = """
print('myglob_var =',myglob_var)
c_list = [ u for u in users ]
print('list comprehension =',c_list)
c_list_with_test = [ u for u in users if flag ]
print('list comprehension with test =',c_list_with_test)
some_result = 'a result'
"""
    nm = globals().copy()
    exec(s, nm, locals())
    print('Result =',nm.get('some_result'))

myfunc()

这一次,它再次触发了同样的问题:users 被定义但不是 flag 在 exec 中:

$ python3 test.py
myglob_var = my global var
list comprehension = ['root', 'service']
Traceback (most recent call last):
  File "test.py", line 19, in <module>
    myfunc()
  File "test.py", line 15, in myfunc
    exec(s, nm, locals())
  File "<string>", line 5, in <module>
  File "<string>", line 5, in <listcomp>
NameError: name 'flag' is not defined

我想在 exec 内部:使用全局变量,传递函数局部变量,能够在本地返回结果并在列表理解测试中使用变量。我还看不到解决方案:您有什么想法吗?

【问题讨论】:

标签: python python-3.x


【解决方案1】:
def myfunc():
    s = """
users = ['root','service']
flag = True
c_list = [ u for u in users ]
print('list comprehension =',c_list)
c_list_with_test = [ u for u in users if flag ]
print('list comprehension with test =',c_list_with_test)
some_result = 'a result'
"""
    nm = {}
    exec(s, nm)
    print('Result =', nm.get('some_result'))

myfunc()

列表理解 = ['root', 'service']

使用 test = ['root', 'service'] 列出理解

结果 = 结果

exec 函数可以仅与一个namespace 字典一起应用。将 nm 变量设为局部变量的命名空间。

更新:

myglob_var = 'my global var'

def myfunc():
    s = """
print('myglob_var =',myglob_var)
users = ['root','service']
flag = True
c_list = [ u for u in users ]
print('list comprehension =',c_list)
c_list_with_test = [ u for u in users if flag ]
print('list comprehension with test =',c_list_with_test)
some_result = 'a result'
"""

    nm = {"myglob_var": myglob_var}
    exec(s, nm)
    print('Result =', nm.get("some_result"))

myfunc()

在命名空间中定义你真正需要的变量是否适合你?

更新 2:

    nm = globals().copy()
    nm.update(locals())
    exec(s, nm)

将你的局部变量传递给命名空间怎么样?

【讨论】:

  • 它不起作用,因为它没有传递全局变量:在我的示例中:NameError: name 'myglob_var' is not defined
  • @Eric 对不起,我没有足够重视你的问题。我已经更新了我的答案。适合你吗?
  • 我编辑了我的问题:比这更复杂:请看一下?
  • @Eric 我已经通过将变量传递给命名空间来更新我的答案。
  • 有趣的是,我们同时找到了相同的解决方案。谢谢。但它没有解释为什么当我在 exec() 中指定 locals 参数时,它会导致列表理解 TEST 中的变量只有未定义...
【解决方案2】:

我终于找到了解决方案,但我觉得这真的很难看:

myglob_var = 'my global var'

def myfunc():
    flag = True
    users = ['root','service']
    s = """
print('myglob_var =',myglob_var)
c_list = [ u for u in users ]
print('list comprehension =',c_list)
c_list_with_test = [ u for u in users if flag ]
print('list comprehension with test =',c_list_with_test)
some_result = 'a result'
"""
    nm = globals().copy()
    nm.update(locals())
    exec(s, nm)
    print('Result =',nm.get('some_result'))


myfunc()

它给出:

$ python3 test.py
myglob_var = my global var
list comprehension = ['root', 'service']
list comprehension with test = ['root', 'service']
Result = a result

它没有解释为什么当我在 exec() 中指定 locals 参数时,它只会导致列表理解 TEST 中的变量未定义...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-04
    • 2014-07-19
    • 2019-05-11
    相关资源
    最近更新 更多