课堂上的奇怪变数

时间:2014-04-26 23:08:55

标签: python class oop

我正在尝试理解Python的类,为此我创建了这个简单的程序:

class TestClass(object):
    b = 3

    def __init__(self):
        self.a = 1
        print '*** INIT ***'
        print self.a, TestClass.b
        print

    def set_all(self):
        self.a *= 2
        TestClass.b *= 2

    def print_all(self):
        print 'PrintAll'
        print self.a, TestClass.b
        print

def main():
    c = TestClass()

    c.a *= 10
    TestClass.b *= 10
    c.b *= 10
    print c.a, TestClass.b, c.b
    print

    c.print_all()

    c.set_all()
    print c.a, TestClass.b, c.b

    TestClass.b
    c.b

if __name__ == '__main__':
    main()

我已经知道var c.a是一个实例var。 Var TestClass.b是一个类/静态var。

我的第一个问题是什么是var c.b?

程序显示它与TestClass.b不同。

我的第二个问题是我何时应该使用class / static vars而不是实例变量?

谢谢,

JM

2 个答案:

答案 0 :(得分:1)

要回答第二个问题,静态变量用于包含有关该类的一些常规信息。举一个简单的例子,让我们假设您有一个Student类,其中包含有关某些班级学生的信息。您使用实例变量“标记”来跟踪对象特定数据。即每个学生的标记。

然而,如果你想跟踪你拥有的学生人数,静态变量就派上用场了。因此,无论何时创建对象,都可以增加静态变量,Student.count将为您提供创建的对象数。

希望这会有所帮助......

关于你的第一个问题,我不认为TestClass.b与c.b不同。这就是我试过的:

>>> class A:
...    b = 3
...    def __init__(self):
...        self.a = 1
...        A.b += 1
...        print self.a,A.b
...
>>> c = A()
1 4
>>> c.b
4
>>> d = A()
1 5
>>> d.b
5
>>> c.b
5

答案 1 :(得分:1)

要回答您的第一个问题,c.b最初是TestClass.b的另一个名称,因为实例b上不存在c属性。但是,只要您使用该名称对其进行赋值(就像使用c.b *= 10一样),就会在b实例上创建一个新的实例变量c,它会影响类变量b。从那时起c.bTestClass.b无关,就像任何其他实例变量一样。

关于你的第二个问题,有几次类变量是有用的。也许最常见的是类常量,预计在整个程序运行期间不会改变。 Python没有任何简单的方法来实际阻止其他用户重新分配它们,但如果你在ALL_CAPITOLS中命名它们并记录它们是不变的,任何与它们混淆的人都应该得到它们造成的任何错误。将常量放在类中意味着您不需要为每个实例反复重新计算它们(或者更糟糕的是,每次调用方法时)。

类变量的另一种用途是用于簿记,例如计算已创建的类的对象数。如果每个实例都需要唯一的ID号,只需将当前计数复制到实例变量中,这可能很有用!当您想要只有有限数量的实例(通常只有一个实例,作为Singleton)时,会出现其他情况。您可以将该实例存储在类变量中并从__new__返回,以防止创建其他实例。

有些程序员喜欢使用类变量作为实例变量的默认值,这些变量可能会在以后创建以遮蔽它们(如问题1所示)。虽然这不是Python的语言设计所禁止的,但我倾向于不喜欢这种代码风格,因为看到一个方法引用看起来像一个尚不存在的实例变量的东西会让人感到困惑。如果您使用可变对象作为类变量默认值,它也可能会严重破坏。我认为最好从一开始就坚持使用实例变量,在__init__中根据需要为它们分配默认值。