python 中的 class 变量会在创建新实例时再次声明吗?

Will a class variable in python be declared again when a new instance is created?

我正在练习以下代码:

class MITPerson(Person): # a subclass of class Person

    nextIdNum = 0 # identification number

    def __init__(self, name):
        Person.__init__(self, name)
        self.idNum = MITPerson.nextIdNum 
        MITPerson.nextIdNum += 1 

    def getIdNum(self):
        return self.idNum

作为参考,这里是超级class:

class Person(object):  # superclass

    def __init__(self, name):
        """Create a person"""
        self.name = name

我认为我已经知道了这个问题的答案,因为我尝试了以下实例:

p1 = MITPerson('Mark Guttag')
p2 = MITPerson('Billy Bob Beaver')
p3 = MITPerson('Billy Bob Beaver')

不足为奇,当我将这些输入控制台时:

在[12]中:p1.getIdNum()

输出[12]: 0

在[13]中:p3.getIdNum()

输出[13]: 2

我已阅读此 post 并查看了此处的所有优秀答案: Static class variables in Python

我看到创建第一个实例p1时,nextIdNum被赋值为0。 我觉得奇怪的是为什么p2和p3不把nextIdNum也重新绑定到0呢? 在我的想象中,一旦 class MITPerson 在不调用方法的情况下创建,class 变量应该被重新分配为 0。

我是不是漏掉了什么?

顺便说一句,我也在这里浏览了教程: https://docs.python.org/3.6/tutorial/classes.html#class-objects

不过,恐怕没有给出答案:(

I saw that nextIdNum is assigned to 0 when the first instance p1 is created.

这是错误的。当定义 class 时,nextIdNum 被赋值为 0。

class 语句是一种对 type 的单次调用的包装。对主体中的语句进行求值,然后将其添加到传递给 type.

dict

你的大致相当于

def _init_(self, name):
    Person.__init__(self, name)
    self.idNum = MITPerson.nextIdNum
    MITPerson.nextIDNum += 1

def _getIdNum(self):
    return self.idNum

MITPerson = type(
    'MITPerson',
    (Person,),
    {
        '__init__': _init,
        'getIdNum': _getIdNum,
        'nextIdNum': 0
    }
)

del _init, _getIdNum

您可以看到 nextIdNum 在创建 MITPerson 的任何实例之前立即初始化为 0,就像 __init__getIdNum.


创建实例时,会发生以下步骤:

  1. MITPerson('Mark Guttag') 解析为 type.__call__(MITPerson, 'Mark Guttag')
  2. __call__ 调用 MITPerson.__new__('Mark Guttag'),创建 MITPerson.
  3. 的新实例
  4. 新值被传递给 MITPerson.__init__,此时在递增 class 变量之前使用 MITPerson.nextIdNum 的当前值。
  5. 一次__init__returns,__new__returns那个值,此时它被赋值给p1.

注意none class 语句主体中的代码再次执行,尽管那里定义的函数__init__