Python:关于变量范围.为什么我不需要将x传递给Y?

Iso*_*ion 7 python variables scope global-variables

考虑以下代码,为什么我不需要将x传递给Y?

class X:    
    def __init__(self):
        self.a = 1
        self.b = 2
        self.c = 3

class Y:        
    def A(self):
        print(x.a,x.b,x.c)

x = X()
y = Y()
y.A()
Run Code Online (Sandbox Code Playgroud)

谢谢你们的答案,他们真的帮我看看问题是什么,即对变量范围的误解.我希望我可以选择两者作为正确的答案,因为他们以自己的方式启发.

roi*_*ppi 8

当python将a编译def成函数时,它会试图弄清楚你引用的东西是否是本地的 - 如果它们不是,你必须指的是全局.例如:

def f():
    print(x)
Run Code Online (Sandbox Code Playgroud)

那么,你没有x在范围内定义f,所以你必须指的是全局.

这就是您上面代码中发生的一切.你没有x在范围内定义A,所以x必须是全球性的.碰巧,你定义全局:

x = X()
Run Code Online (Sandbox Code Playgroud)

在你打电话之前:

y = Y()
y.A()
Run Code Online (Sandbox Code Playgroud)

所以一切顺利.

如果你要"嗯,我不确定我是否相信你,roippi"只看字节码:

dis.dis(Y.A)
  3           0 LOAD_GLOBAL              0 (print) 
              3 LOAD_GLOBAL              1 (x) # aha
              6 LOAD_ATTR                2 (a) 
              9 LOAD_GLOBAL              1 (x) # aha!
             12 LOAD_ATTR                3 (b) 
             15 LOAD_GLOBAL              1 (x) # aha!!
             18 LOAD_ATTR                4 (c) 
             21 CALL_FUNCTION            3 (3 positional, 0 keyword pair) 
             24 POP_TOP              
             25 LOAD_CONST               0 (None) 
             28 RETURN_VALUE     
Run Code Online (Sandbox Code Playgroud)

啊哈.


小智 1

来自Python教程

\n\n
\n

尽管作用域是静态确定的,但它们是动态使用的。\n 在执行期间的任何时候,至少存在三个嵌套作用域\n,其命名空间可直接访问:

\n\n
    \n
  • 首先搜索的最里面的范围包含本地名称
  • \n
  • 从最近的封闭作用域开始搜索的任何封闭函数的作用域包含非局部的,但也包含
  • \n
  • 非全局名称倒数第二个范围包含当前模块\xe2\x80\x99s
  • \n
  • 全局名称最外层范围(最后搜索)是包含内置名称的名称空间
  • \n
\n
\n\n

在您的情况下x=X()放入x全局名称空间。由于你没有xY.A (最内层作用域)本地定义,所以python使用上述规则搜索变量定义,发现\'x\'是在最外层作用域中定义的。因此,当您引用x.a它时Y.A,它就解决了。

\n