Python 类中的变量范围

Posted

技术标签:

【中文标题】Python 类中的变量范围【英文标题】:Variable scopes in Python classes 【发布时间】:2022-01-11 08:25:20 【问题描述】:

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

在类中的函数内声明变量:只有该函数可以访问它(它在该函数的范围内)

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

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

还有其他我应该知道的细微差别,或者我已经知道了吗?

【问题讨论】:

但是基本上,是的,ypu 在 Python 中默认没有“私有”变量之类的东西(我说“默认”是因为人们可以使用一些自省魔法来获得类似私有/受保护的行为) .现在,为什么需要私有变量?约定是名称以单个“_”开头的方法/属性不是公共的,不应从对象外部修改。用于混淆/安全的私有变量的想法本质上是错误的。 【参考方案1】:

由于您问题中的列表不是 100% 清楚,我决定用一个简单的例子来解释它。它还包括一些您未在列表中提及的变量,例如 __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.aself._x 的赋值会创建一个新的实例变量。它被认为是“不是公共 API 的一部分”(又名受保护),但从技术上讲,它没有不同的行为。 对self.__y 的赋值会创建一个名为_Test__y 的新实例变量,也就是说,它的名称是错位的,因此除非您使用错位名称,否则它不能从类外部访问。这可用于“私有”变量。 对b 的赋值会创建一个局部变量。除了 __init__ 函数之外,它在任何地方都无法使用,因为它没有保存在实例、类或全局范围内。

【讨论】:

您不使用Test(object) 有什么原因吗?那么你的答案是否也适用于new-type 类? @DavorJosipovic 有个东西叫 Python3。 如果我们像这样调用类:** obj = Test("name") ** 那么这个 obj 是实例或对象。这个 obj 到底是什么。 另外,__init__(self, a) 中的参数a 仅是__init__ 中的局部变量。【参考方案2】:

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

您可以使用下划线实现某种程度的访问控制。见private variables in the Python tutorial。按照惯例,变量以一个下划线开头,例如_foo 是 API 的非公开部分,名称以两个下划线开头,例如__foo 的名称 mangled 将变为 _classname__foo

【讨论】:

【参考方案3】:

虽然已回答,但让我为您的问题添加一些 cmets:

在类中声明一个变量(在函数之外):所有类函数都可以访问它(基本上是一个公共变量): 注释:这就像一个静态变量,可以使用类名来调用。这些变量对所有函数都可用,任何函数都可以修改并打印出来。

在类内的函数内声明变量:只有该函数可以访问它(在该函数范围内): 注释:如果变量声明时没有 self ,那么它只能在该函数中访问,有点像局部变量。但是,如果它声明使用 self like self.var= 'somevalue', 那么它可以通过任何对象访问,但不能通过类名访问。

在类中的函数内用 self.(variable name) 声明一个变量:所有类函数都可以访问它(这与全局(变量名)有何不同?): 评论:见上部分的答案。

并且由于没有私有/受保护,所有内容都是公共的,因此可以从类内部访问的所有内容都可以从类外部访问。: 评论:是的,但是我们可以使用单个下划线来告诉世界这个变量是私有的,但从技术上讲实际上并没有使它成为私有。

【讨论】:

【参考方案4】:

我们可以将 this 的作用域用于 as : 案例 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 的变化值

【讨论】:

以上是关于Python 类中的变量范围的主要内容,如果未能解决你的问题,请参考以下文章

类中的 PHP 全局变量范围

Python 类中的列表理解范围规则是啥? [复制]

python 类中的变量传递给类中的函数

在同一类中的 setTimeout 期间维护变量

类中的条件语句,但在函数范围之外

Python中的类和方法使用举例