【问题标题】:How can I pass my locals and access the variables directly from another function?如何传递我的本地人并直接从另一个函数访问变量?
【发布时间】:2009-08-14 12:08:57
【问题描述】:

假设我有这个:


def a(dict):
  locals().update(dict)
  print size

def b():
  size = 20
  f(locals())

我需要做什么才能直接从a 函数访问size 变量?我知道:


size = dict["size"]

但我认为应该有更直接的方法。我尝试使用locals().update(dict),但没有奏效。有没有更好的办法?

【问题讨论】:

  • 你到底想做什么?
  • 我想直接访问变量,而不是通过locals["size"]
  • 你的大局是什么?可能有更好的方法。
  • 如果你想从另一个函数访问变量,它们不是“本地的”,它们是“全局的”。您需要这么多全局变量来做什么?
  • 函数b()的最后一行不应该是a(locals())吗?

标签: python variables function language-features


【解决方案1】:

Python 编译器通过在编译时识别函数正在访问的裸名是否是本地的(即分配或绑定在函数内的裸名)来优化对局部变量的访问。所以如果你编码:

def lv1(d):
  locals().update(d)
  print zap

编译器“知道”barename zap 不是本地名称(未在函数 lv1 中分配),因此它编译代码以将其作为全局访问——d 包含的任何内容都无关紧要。

如果您喜欢缓慢而臃肿的代码,您可以通过在函数内部使用 exec 来取消优化 - 当编译器看到关键字 exec 时,它知道您正在尝试让您的代码变慢,尽可能臃肿和错误,因此它通过不以任何方式进行优化来进行协作。

因此,以下代码可以按您的意愿工作:

def lv1(d):
  exec ""
  locals().update(d)
  print zap

lv1({'zap': 23})

它会根据需要发出23

我希望从上面的“面无表情的幽默”中可以清楚地看出,不推荐使用该技术,但我最好非常明确地说明它:为了写 print zap 代替 print locals()['zap'] 的可疑句法乐趣,你在性能方面付出了沉重的代价。尽管如此,就像各种危险工具一样,对于真正有经验的大师级程序员来说,这些工具在罕见的用例中很有用,他们真正知道自己在做什么以及为什么,exec 在那里,可供您使用(或误用)随心所欲使用):Python 不会妨碍您!-)

【讨论】:

  • 这似乎是一个真正依赖于所使用的 Python 版本的 hack。是否可以保证这将继续有效?
  • 它必须在任何兼容的 Python(1.* 或)2.* 实现中工作;它不能也不能在任何兼容的 3.* 实现中工作,因为制作 Python 3 的全部目的是使我们能够以这种方式打破向后兼容性。但是,即使print goo 停止在 Python 3 中工作(必须是 print(goo) 那里),所以 exec 语法和语义的类似弱化相比之下几乎不是一个主要问题;-)。
  • 为什么有一个裸字符串发送到exec
  • @Geo,你execing 是什么字符串并不重要——仅仅 presenceexec 语句在函数范围内没有特定的字典就可以说明Python 编译器(在 Python
  • @martinako,我相信 Python 3 不允许对函数的本地命名空间进行如此任意、大规模的污染,不; exec 现在是一个内置函数,甚至不再是一个语句。
【解决方案2】:

这对你有帮助吗?

def print_size(size=None):
    print(size)

dict = {'size': 'XXL'}
print_size(**dict)

【讨论】:

    【解决方案3】:

    你可以使用闭包来访问另一个函数的作用域:

    def b():
    
      def a():
        print size
    
      size = 20
      a()
    

    诀窍是将属于彼此的函数堆叠在一起。这样内部函数 a 可以访问外部函数 b 的局部变量。

    但我不知道你到底在做什么,所以我不确定这是否有帮助。

    【讨论】:

      【解决方案4】:
      print size
      

      无法工作,因为在编译代码时“大小”是未知的。如果您像这样更改代码,您的代码将起作用:

      def a(dict):
          locals().update(dict)
          print locals()["size"]
      
      def b():
          size = 20
          a(locals())
      

      但正如您对问题的评论已经表明:这是非常奇怪的代码。如果你解释你真正想做的事情,我很确定会有更好的解决方案。

      【讨论】:

        【解决方案5】:

        我知道,我知道,这个问题已经很老了,并且接受的答案已经很好了。

        只是添加两美分,因为它看起来很明显但没有提及:通过显式为其分配一个(默认)值来使大小本地化。

        def a(dict):
            size = 20  # size default value <- quick (and dirty?) fix
            locals().update(dict)
            print (size)
        
        def b():
            size = 20
            a(locals())
        

        因此,a() 中添加的行 (size = 20) 使 size 成为实际的局部变量,无需 exec,兼容 python3 且没有优化缺陷。

        那怎么会有用???

        好吧,有了它,我们可以在 python2 中实现类似def f(x, *args, y=10) 的东西,因为这会在 python2 中引发语法错误,但只在 python3 中有效:

        def f(x, *args, **kwargs):
           y = 10
           locals().update(kwargs)
           print (x, y)
        

        上面的例子适用于python2和python3

        【讨论】:

          猜你喜欢
          • 2023-03-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-12
          相关资源
          最近更新 更多