Python类中的变量作用域

83

在类中声明变量(在函数外):所有的类函数都可以访问它(基本上是公共变量)

在类的函数内部声明变量:只有该函数可以访问它(它在该函数的作用域内)

在类的函数内使用 self.(变量名) 声明变量:所有类函数都可以访问它(这与 global (变量名) 有什么不同?)

由于没有私有/受保护的概念,所以一切都是公开的,因此从类的内部可以访问的所有内容也可以从类的外部访问。

还有其他需要注意的细节吗,或者我已经全面理解了吗?


1
但基本上,是的,在Python中默认情况下没有像“private”变量这样的东西(我说“默认情况下”,因为可以使用一些内省魔法来实现私有/受保护的行为)。那么,为什么需要私有变量?约定是,名称以单个“_”开头的方法/属性不是公共的,不应该从对象外部修改。私有变量用于混淆/安全性的想法本质上是错误的。 - jsbueno
4个回答

167

因为您提供的列表并不是完全清晰的,所以我决定用一个简单的例子来解释它。它还包括一些您在列表中未提及的__something变量。

class Test:
    a = None
    b = None

    def __init__(self, a):
        print self.a
        self.a = a
        self._x = 123
        self.__y = 123
        b = 'meow'

刚开始,ab只是定义在类本身的变量-可以通过Test.aTest.b访问,而不是特定于任何实例。

当创建该类的一个实例(这导致__init__被执行)时:

  • print self.a找不到实例变量,因此返回类变量
  • self.a = a: 创建一个新的实例变量a。它遮盖了类变量,所以self.a现在引用实例变量;要访问类变量,现在必须使用Test.a
  • self._x的赋值创建一个新的实例变量。它被认为是“非公共API”(又名protected),但从技术上讲,它没有不同的行为。
  • self.__y的赋值创建一个名为_Test__y的新实例变量,即其名称被mangled,因此除非使用mangled名称,否则无法从类外部访问它。这可用于“私有”变量。
  • b的赋值创建一个局部变量。它仅在__init__函数中可用,因为它未保存在实例、类或全局范围内。

你为什么不使用 Test(object)?这个答案是否也适用于 new-type 类呢? - Davor Josipovic
2
@DavorJosipovic,有一种叫做Python3的东西。 - Ekrem Dinçel
如果我们这样调用类:** obj = Test("name") **,那么这个obj就是实例或对象。它到底是什么? - Lord-shiv
另外,在 __init__(self, a) 中的参数 a 只是 __init__ 函数内的本地变量。 - wisbucky

25

在类的顶层声明一个变量就像声明一个静态或类变量一样。用self限定符声明它是一个实例变量。类变量可以通过类名引用进行修改(例如 Class.x = 5),所有实例将继承这些更改。实例变量是私有于实例的,并且只能由该实例修改。

您可以使用下划线实现一定程度的访问控制。请参见Python教程中的私有变量。按照惯例,以下划线开头的变量,例如 _foo 是API的非公共部分,以双下划线开头的名称,如__foo 将其名称修改为 mangled_classname__foo


1

虽然已经有答案了,但是我想对你的问题补充一些评论:

在类中声明一个变量(在函数外):所有类函数都可以访问它(基本上是公共变量)

这就像一个静态变量,可以使用类名调用。这些变量对所有函数都可用,任何函数都可以修改并打印它。

在类的函数内部声明一个变量:只有该函数可以访问它(它在该函数的作用域内):

如果变量没有使用self声明,则仅在该函数内部可访问,就像局部变量一样。但是,如果使用self声明,例如self.var= 'somevalue',则可以通过任何对象访问,但不能通过类名访问。

在类的函数内使用self.(variable name)声明一个变量:所有类函数都可以访问它(与global (variable name)有何不同?)

请参见上面部分的答案。

由于没有私有/受保护的内容,所以所有内容都是公开的,因此从类内部访问的所有内容都可以从类外部访问

是的,但我们可以使用单个下划线来告诉世界这个变量是私有的,但从技术上讲,这并不能使它成为私有的。


-1

我们可以在以下情况下使用此范围: 情况1:在类中

class test:
     def __init__(self, a):
          self.__elements = a
     def change_a(self): self.__elements = 5

第 2 案例: 类外

t = test(5)

这将通过 object._classname__privatevaribalename 访问

print(t._test__elements)

这将打印出a的变化值


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