Python 3 - 直接操作 class' 属性是否会覆盖其对象的相同属性,从而使属性成为纯静态的? [解决了]

Python 3 - Does the direct manipulation of a class' attribute override the same attribute for its objects making the attribue purely static? [SOLVED]

在了解 classes 在 Python 中的工作原理时,我遇到了一个 class 定义示例,它在我看来有点奇怪。

该示例的目的是演示如何在 Python 中实现静态变量的行为。例子是这样写的:

class MemberCounter:
    members = 0
    def init(self):
        MemberCounter.members += 1


m1 = MemberCounter()
m1.init()
m2 = MemberCounter()
m2.init()

设置 class 并创建对象后,我打印了 'members' 属性的值。这些是结果:

MemberCounter.members = 2

m1.members = 2

m2.members = 2

那是我感到困惑的时候。当我期待 'MemberCounter.members = 2' 时,其他两个结果对我来说毫无意义 - 为什么 'm1' 和 'm2' 对象的 'members' 值都等于 2?我认为这两个值都应该是 0 - 如果被更改的唯一属性是附加到 MemberCounter class 的 'members' 属性,为什么它会导致对自己的唯一 'members' 每个 class' 对象的值。看起来 'members' 属性在每个对象的 init() 函数中的地址类似于 'MemberCounter.members += 1',完全覆盖了 m1.members[=54 的唯一值=] 和 m2.members 引用并将它们的指针重定向到 MemberCounter.members 值,使所有三个指针都指向相同的值

==> m1.members = m2.members = MemberCounter.members.

此外,我尝试以相反的方式定义 class(增加 self.members 而不是 MemberCounter.members ):

class MemberCounter:
    members = 0
    def init(self):
        self.members += 1


m1 = MemberCounter()
m1.init()
m2 = MemberCounter()
m2.init()

这个定义产生了合乎逻辑的结果(这让我对上面提到的奇怪行为更加好奇):

MemberCounter.members = 0

m1.members = 1

m2.members = 1

简而言之,我很好奇为什么第一个 class 定义的行为如此奇怪?为什么仅仅'MemberCounter.members += 1'语句就完全删除了'm1.members'和'm2.members' 拥有独特的价值,并使其等于 MemberCounter.members 价值。

我希望我能够清楚地提出我的问题,我将非常高兴能深入了解这种奇怪的行为:)

您可以 读取 带有 instance.attribute 符号的静态属性作为更自然的 class.attribute 符号的替代,是 [=34 中的预期功能=].

来自documentation

Both static data and static methods (in the sense of C++ or Java) are supported in Python.

For static data, simply define a class attribute. To assign a new value to the attribute, you have to explicitly use the class name in the assignment:

class C:
    count = 0   # number of times C.__init__ called

    def __init__(self):
        C.count = C.count + 1

    def getcount(self):
        return C.count  # or return self.count

c.count also refers to C.count for any c such that isinstance(c, C) holds, unless overridden by c itself or by some class on the base-class search path from c.__class__ back to C.

Caution: within a method of C, an assignment like self.count = 42 creates a new and unrelated instance named “count” in self’s own dict. Rebinding of a class-static data name must always specify the class whether inside a method or not:

C.count = 314

第一个代码块下方的段落解释了您的疑虑。 “注意”段落解释了您发现的合乎逻辑的内容。