0

我实际上想创建一个新的本地。我知道这听起来很可疑,但我认为我有一个很好的用例。本质上我的问题是,当我尝试打印鸡蛋时,此代码会抛出“NameError:未定义全局名称'eggs'”:

def f():
    import inspect
    frame_who_called = inspect.stack()[1][0]
    frame_who_called.f_locals['eggs'] = 123

def g():
    f()
    print(eggs)

g()

我发现了这个旧东西: http: //mail.python.org/pipermail/python-dev/2005-January/051018.html

这意味着我可能能够使用 ctypes 并调用一些秘密函数来做到这一点,尽管他们只讨论了更新一个值。但也许有更简单的方法?

4

3 回答 3

3

我对您的用例非常好奇。你到底为什么要在调用者的框架中插入一个新的本地,而不是简单地做这样的事情:

def f():
    return 123

def g():
    eggs = f()
    print(eggs)

毕竟,您可以返回一个包含任意多个值的元组:

def f():
    return 123, 456, 789

def g():
    eggs, ham, bacon = f()
    print(eggs, ham, bacon)
于 2009-10-07T21:47:27.683 回答
2

正如 Greg Hewgill 在对该问题的评论中提到的那样,我回答了另一个关于在 Python 3 中进行修改的问题,locals我将在这里进行一些回顾。

Python 3 错误列表上有一篇关于此问题的帖子——它在 Python 3 手册中的记录有些差。Python 3 使用数组作为局部变量,而不是像 Python 2 那样使用字典——优点是查找局部变量的时间更快(Lua 也这样做)。基本上,数组是在“字节码编译时”定义的,不能在运行时修改。

具体请参阅Georg Brandl 的文章中的最后一段,以了解有关为什么这不能(并且可能永远不会)在 Python 3 中工作的详细信息。

于 2009-10-08T00:32:52.657 回答
1

在 Python 2.* 中,您可以通过破坏局部变量的正常优化来使此类代码正常工作:

>>> def g():
...   exec 'pass'
...   f()
...   print(eggs)

exec语句的存在导致 Python 2 以g完全非优化的方式编译,因此本地变量位于 dict 中,而不是像通常那样位于数组中。(性能损失可能相当大)。

这种“去优化”在 Python 3 中不存在,其中exec不再是一个语句(甚至不是关键字,只是一个函数)——即使在它后面加上括号也无济于事......:

>>> def x():
...   exec('a=23')
...   print(a)
... 
>>> x()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in x
NameError: global name 'a' is not defined
>>> 

即,现在甚至exec不能“创建局部变量”,在时间上不知道def(即,当编译器完成它的传递以将函数体转换为字节码时)。

你最好的选择是放弃。第二好的方法是让你的f函数将新名称注入调用者的globals——毕竟这些仍然是一个字典。

于 2009-10-08T01:47:40.713 回答