我正在尝试为特定类创建的所有实例的计数器。
很明显,我的代码不会超过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中处理静态。我投票决定关闭我的问题,但讨厌答案是否会消失。
答案 0 :(得分:5)
以下是我将如何做到这一点(虽然你的代码对我来说很好,所以我怀疑它不是你实际运行的代码来观察问题)。
class Feature(object):
counter = 0
def __init__(self):
self.id = Feature.counter
Feature.counter += 1
如果您愿意,可以将Feature
替换为type(self)
(或self.__class__
,同样的事情),但请注意,如果存在子类,它们的行为会有所不同(可能这是您的问题) ,实际上)。
在Python中使用类/实例变量的规则非常简单,它有助于牢记这些:
self.name
读取属性的值将回退到self
类,如果self
不直接包含名为{{的属性,则返回到基类层次结构1}}。name
创建属性的值始终 直接在self.name = ...
中绑定name
。特别是,当写一个值时,它并不重要在分配之前对相同属性的读取就已经消失了。
因此,如果在您的实际程序中,您正在实例化self
的子类,我将其称为Feature
,然后这一行:
Sub
可能不会达到您的预期。它将从self.__class__.counter = self.__class__.counter + 1
(第一次创建Feature.counter
的实例)读取,但将写入Sub
。此后,读取将转到Sub.counter
(因为它现在存在),因此Sub.counter
实例将获得增加的ID,但它们不会增加Sub
的值,因此实例Feature.counter
的其他子类可以获得重复的ID。
所以如果我将Feature
视为生成在Feature.counter
命名空间中的全局变量,我会使用counter
,我想要Feature
的所有子类分享同一个柜台。如果我希望Feature
的每个子类都有自己独立的计数器(但是你需要做一些事情来初始化它们),我会使用type(self).counter
。
答案 1 :(得分: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
答案 2 :(得分:1)
在尝试计算实例时,我更喜欢这种范例:
from itertools import count
class MyClass():
_getId = count(0).next
def __init__(self):
self.id = self._getId()
答案 3 :(得分:0)
为什么不使用类名本身,比如
self.id = Feature.counter
Feature.counter += 1