0

我正在尝试为为特定类创建的所有实例创建一个计数器。很明显,我的代码不会self.__class__.counter超过 1。我做错了什么?

 class Feature(object):
    counter = 0
    def __init__(self, line):
        self.id = self.__class__.counter
        self.__class__.counter = self.__class__.counter + 1
    def __repr__(self):
        return "Feature: id=%d name=%s" % (self.id,self.name,)

更新: 此代码实际上按预期工作。聪明的人留下了一些非常详细的解释如何在 python 中处理静态。我投票结束我的问题,但讨厌答案会消失。

4

4 回答 4

6

这就是我的做法(虽然你的代码对我来说很好,所以我怀疑这不是你实际运行来观察问题的代码)。

class Feature(object):
    counter = 0

    def __init__(self):
        self.id = Feature.counter
        Feature.counter += 1

You can replace Feature by type(self) (or self.__class__, same thing) if you prefer, but note that they'll behave differently in the presence of subclasses (maybe that's your problem, actually).

The rules for using class/instance variables are very simple in Python, and it helps to keep them in mind:

  1. Reading the value of an attribute with self.name will fall back to the class of self, and then to the base class hierarchy if self does not directly contain an attribute named name.
  2. Writing the value of an attribute with self.name = ... always binds name directly in self.

In particular, when writing a value it does not matter where a read to the same attribute would have gone before the assignment.

So if in your actual program you're instantiating a subclass of Feature, which I'll call Sub then this line:

self.__class__.counter = self.__class__.counter + 1

will probably not do what you expect. It will read from the Feature.counter (the first time you create an instance of Sub), but will write to Sub.counter. Thereafter the reads will go to Sub.counter (because it exists now), and so the Sub instances will get increasing ids, but they're not increasing the value of Feature.counter, so instances of other subclasses of Feature can get duplicate ids.

So I'd use Feature.counter if I was thinking of counter as a global variable living in the Feature namespace, and I wanted all the subclasses of Feature to share the same counter. I'd use type(self).counter if I expect each and every subclass of Feature to have its own independent counter (but then you'd need to do something to initialise them).

于 2013-03-18T22:18:29.363 回答
1

self.__class__.attribute为了更好地说明和之间的区别ClassName.attribute

class Feature(object):
    counter = 0

    def __init__(self):
        self.id = self.__class__.counter
        self.__class__.counter += 1

class Sub(Feature):
    def __init__(self):
        super(Sub, self).__init__()        

print [(vars(Feature()), vars(Sub())) for i in xrange(3)]
print Feature.counter, Sub.counter, id(Feature.counter) == id(Sub.counter)


class Feature(object):
    counter = 0

    def __init__(self):
        self.id = Feature.counter
        Feature.counter += 1

class Sub(Feature):
    def __init__(self):
        super(Sub, self).__init__()


print [(vars(Feature()), vars(Sub())) for i in xrange(3)]
print Feature.counter, Sub.counter, id(Feature.counter) == id(Sub.counter)

>>> [({'id': 0}, {'id': 1}), ({'id': 1}, {'id': 2}), ({'id': 2}, {'id': 3})]
3 4 False
>>> [({'id': 0}, {'id': 1}), ({'id': 2}, {'id': 3}), ({'id': 4}, {'id': 5})]
6 6 True
于 2013-03-18T22:10:24.897 回答
1

在尝试计算实例时,我更喜欢这种范例:

from itertools import count

class MyClass():
  _getId = count(0).next
  def __init__(self):
    self.id = self._getId()
于 2013-03-18T22:14:34.767 回答
0

为什么不使用类名本身,比如

self.id = Feature.counter
Feature.counter += 1
于 2013-03-18T22:04:28.403 回答