【问题标题】:python: name resolution clarification?python:名称解析说明?
【发布时间】:2019-09-13 18:21:42
【问题描述】:

我正在阅读 python 参考资料name resolution,内容为

类定义是可以使用和定义名称的可执行语句。这些引用遵循名称解析的正常规则,但在全局命名空间中查找未绑定的局部变量。

基于此,我期望以下代码

x = 10

def f():
    x = 5

    class Test:
        y = x

    return Test

print(f().y)

打印10,但是它打印5。这是参考中的错误,还是我误解了什么?

【问题讨论】:

  • 你在函数内部将Test.y设置为x,其中x是5。f()返回Test,所以f().yTest.y,也就是5。为什么你期待 10 个吗?
  • @khelwood:因为它说在类定义块中未绑定的名称在全局中查找,这与规则相反。这里发生的事情似乎遵循标准规则
  • 它说“在全局命名空间中查找未绑定的局部变量”。 x 不是未绑定的局部变量。
  • @khelwood:按照我的理解,在类定义的上下文中,它的意思是 unbound,而不是函数。另外,我看不出当前的行为是对标准规则的期望
  • class 语句不能有自己的局部变量,因为class 语句没有建立新的范围。这是一个奇怪的伪作用域,y 会暂时隐藏任何“外部”y,直到 class 语句完成,但在任何方法的定义中都会被忽略。

标签: python


【解决方案1】:

在这种情况下,“正常”规则适用:

x = 'global'

def f():
    x = 'defined in f'

    class Test:
        print(x) # not local, normal rules apply

f()
# defined in f

在第二种情况下,如果我们在函数内部,我们会期望 UnboundLocalError: local variable 'x' referenced before assignment

x = 'global'

def f():
    x = 'defined in f'

    class Test:
        print(x) # unbound local at this time
        x = 'assigned in Test'
        print(x)

但对于第一个print(x)x 将取自全局命名空间:

f()
# global
# assigned in Test

【讨论】:

    【解决方案2】:

    我认为@khelwood 给出了答案。变量中的值:

    测试.y

    是一个你定义的整数,但你永远不会给函数 x = 10。

    也许你真正想要的是:

    x = 10
    def f(x=5):
        class Test:
            y = x
        return Test
    print(f().y) #print default 5
    print(f(x).y) 
    

    最后一行打印 10,因为 x 被赋予函数,因此类将 y 设置为 x

    【讨论】:

      【解决方案3】:

      您可以通过将f 包装在另一个定义局部变量x 的函数中来查看异常:

      x = 10
      
      def g():
          x = 7
          def f():
              class Test:
                  y = x
      
              return Test
          return f()
      
      print(g().y)
      

      现在输出为 7,因为在 class 语句中查找 x 会绕过 g 的本地范围以查找 x 的全局值。

      在您的代码中,因为class 建立了一个新的命名空间,而不是一个新的范围,所以x 的值取自当前本地范围, f.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-21
        • 1970-01-01
        相关资源
        最近更新 更多