Python变量作用域和类

7
在Python中,如果我定义一个变量:
my_var = (1,2,3)

尝试在类的__init__函数中访问它:

class MyClass:
    def __init__(self):
        print my_var

我可以访问并打印my_var而不需要声明(global my_var)。

然而,如果我把my_var放在class MyClass之后,我会得到作用域错误(no global variable found)

这是什么原因?我应该怎么做?在哪里可以阅读相关信息来学习?我已经阅读了Python类页面,但没有找到解释。

谢谢


当您将变量放入类中时,它就不再是全局变量了。 - Ashwini Chaudhary
4个回答

12
补充@mgilson的答案: 请注意,Python类变量在类实例之间共享。这种行为可能非常意外和奇怪。实际上,它的工作方式如下:
class MyClass(object):
    my_var = 10

    def __init__(self):
        print(self.my_var)


m1 = MyClass()
print(m1.my_var)
>>> 10          # this is fine

MyClass.my_var = 20
print(m1.my_var)
>>> 20          # WTF? :) --> shared value

m2 = MyClass()
print(m2.my_var)
>>> 20          # this is expected

m1.my_var = 30
print(MyClass.my_var)
>>> 20          # this is also expected

MyClass.my_var = 40 
print(m1.my_var)
>>> 30           # But WHY? Isn't it shared? --> 
                 # The value WAS shared until m1.my_var = 30 has happened.

print(m2.my_var)
>>> 40           # yep m2.my_var's value is still shared :)

BasicWolf,由于@mgilson的回答更加相关,我不得不选择它作为正确答案。但是我非常感谢您提供的这个优秀、真正精彩的解释。它让我理解了很多,除了mgilson澄清的内容之外。非常感谢! - Phil

11
当你把它放在class MyClass之后,它就成为一个类属性,你可以通过MyClass.my_var或者在类内使用self.my_var来访问它(前提是你没有创建一个同名的实例变量)。
这里有一个小演示:
my_var = 'global'
class MyClass(object):
   my_var = 'class' 
   def __init__(self):
      print my_var #global
      print MyClass.my_var #class
      print self.my_var #class -- Only since we haven't set this attribute on the instance
      self.my_var = 'instance' #set instance attribute.
      print self.my_var #instance
      print MyClass.my_var #class

如果你把它放在__init__中,这意味着只有在创建对象时才会初始化。 - ronak
当没有创建名为my_var的实例属性时,尝试访问它将返回类属性而不是全局变量。 - jsbueno
@jsbueno - 我之前已经运行过它了 - 类变量是(1,2,3),全局变量是(4,5,6),我不确定我理解你的意思... - mgilson
更改为使用更有意义的数据来表示变量(以便更容易跟踪哪个是哪个) - mgilson
@mgilson 我的意思是,如果你在类定义中使用 my_var(就在 class MyClass 后面),那么它就是一个类变量。如果你将它包含在 __init__ 函数中,你将需要创建一个对象来访问该变量。你的回答是正确的,我给了你一个赞。 - ronak
显示剩余2条评论

2

如果您写下:

class MyClass(object):
    my_var = (1, 2, 3)

你正在定义一个MyClass的属性,而不是一个变量。在你的__init__方法中,它是MyClass.my_var


1

一旦它在class定义中,它就不再是全局的了,现在它在类对象的命名空间中。你可以在__init__中使用self.my_var来访问它...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接