Here is how I would do it (though your code works fine for me, so I suspect it's not the code you're actually running to observe the problem).
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:
- Reading the value of an attribute with
self.name
will fall back to the class ofself
, and then to the base class hierarchy ifself
does not directly contain an attribute namedname
. - Writing the value of an attribute with
self.name = ...
always bindsname
directly inself
.
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).