在__init__中更改类属性

use*_*609 5 python python-2.7 python-internals

我正在查看Stack Overflow问题计算类的实例?,我不确定为什么该解决方案有效,而使用简单添加的解决方案则不然.我想这更像是一个关于如何存储和访问类与实例变量的问题.

这是我认为应该起作用的代码,但代之以4id:

class foo():
      num = 3    # trying 3 instead of 0 or 1 to make sure the add is working

      def __init__(self):
        self.num += 1
        self.id = self.num

f = foo()
g = foo()

print f.id    # 4
print g.id    # 4
Run Code Online (Sandbox Code Playgroud)

self.num +=1声明有些工作(增加正在发生,但不是作业).

正在进行这项任务的情况下发生的事情在这里失败,而itertools.count任务在另一个问题的解决方案中成功了吗?

Dan*_*man 5

self.num += 1基本上是指“取的值self.num,将其递增,然后分配给” self.num

self如果没有相应的实例变量,则在其上查找属性将找到类变量。但是,分配将始终写入实例变量。因此,这尝试查找实例var,失败,退回到类var,获取值,将其递增,然后分配给实例var

链接问题的答案起作用的原因是因为没有分配正在进行;他们next()直接在类变量上调用,其值被更改,但未重新分配名称。


jon*_*rpe 5

整数不实现__iadd__(就地添加,for +=),因为它们是不可变的.解释器回退到标准分配__add__,所以行:

self.num += 1
Run Code Online (Sandbox Code Playgroud)

变为:

self.num = self.num + 1
Run Code Online (Sandbox Code Playgroud)

在右侧,你得到foo.num(即3)via self.num,如你所料,但这里有趣的是分配给instance属性num 阴影 class属性.所以这条线实际上相当于:

self.num = foo.num + 1  # instance attribute equals class attribute plus one
Run Code Online (Sandbox Code Playgroud)

所有的情况下结束了self.num == 4保持foo.num == 3.相反,我怀疑你想要的是:

foo.num += 1  # explicitly update the class attribute
Run Code Online (Sandbox Code Playgroud)

或者,您可以将其实现为a @classmethod,更明确地处理类:

class Foo():  # note naming convention

    num = 3

    def __init__(self):
        self.increment()
        self.id = self.num  # now you're still accessing the class attribute

    @classmethod
    def increment(cls):
        cls.num += 1
Run Code Online (Sandbox Code Playgroud)