在创建新实例时,是否会再次声明python中的类变量?

时间:2018-03-28 15:08:47

标签: python class static-variables

我正在练习以下代码:

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 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()

Out [12]:0

在[13]中:p3.getIdNum()

Out [13]:2

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

我看到在创建第一个实例p1时,nextIdNum被赋值为0。 我觉得奇怪的是,为什么p2和p3也不能再次将nextIdNum绑定到0? 在我的想象中,一旦创建了一个类MITPerson而没有调用该方法,就应该将类变量重新赋值为0。

我错过了什么吗?

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

然而,我担心它没有给出答案:(

2 个答案:

答案 0 :(得分:9)

  

我看到在创建第一个实例p1时,nextIdNum被赋值为0。

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

答案 1 :(得分:2)

class语句是对type的单个调用的一种包装。评估正文中的语句,然后将其添加到传递给dict的{​​{1}}。

你的大致相当于

type

您可以看到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的任何实例之前立即初始化为0,就像MITPerson__init__一样。

创建实例时,会执行以下步骤:

  1. getIdNum解析为MITPerson('Mark Guttag')
  2. type.__call__(MITPerson, 'Mark Guttag')调用__call__,这会创建MITPerson.__new__('Mark Guttag')的新实例。
  3. 新值传递给MITPerson,此时在递增类变量之前使用MITPerson.__init__的当前值。
  4. MITPerson.nextIdNum返回后,__init__会返回该值,此时会将其分配给__new__
  5. 请注意,p1语句正文中的代码不会再次执行,尽管其中定义的函数class是。