【问题标题】:Will a class variable in python be declared again when a new instance is created?创建新实例时会再次声明python中的类变量吗?
【发布时间】:2018-09-07 08:26:24
【问题描述】:

我正在练习以下代码:

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

输出[12]:0

在[13]:p3.getIdNum()

输出[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

但是,恐怕它并没有给出答案:(

【问题讨论】:

  • 一个类变量是类的一个属性。除非您更改类对象本身,否则它不会改变。

标签: python class static-variables


【解决方案1】:

我看到在创建第一个实例 p1 时将 nextIdNum 分配为 0。

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

【讨论】:

    【解决方案2】:

    class 语句是对 type 的单个调用的一种包装。对正文中的语句进行求值,然后将其添加到传递给 typedict

    你的大致相当于

    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. 新值被传递给MITPerson.__init__,此时MITPerson.nextIdNum的当前值在增加类变量之前被使用。
    4. 一旦__init__ 返回,__new__ 返回该值,此时将其分配给p1

    请注意,class 语句主体中的任何代码都不会再次执行,尽管在那里定义的函数 __init__ 会再次执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-17
      • 1970-01-01
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      相关资源
      最近更新 更多