Python静态变量分辨率

时间:2013-03-18 21:57:19

标签: python static static-variables

我正在尝试为特定类创建的所有实例的计数器。 很明显,我的代码不会超过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 个答案:

答案 0 :(得分:5)

以下是我将如何做到这一点(虽然你的代码对我来说很好,所以我怀疑它不是你实际运行的代码来观察问题)。

class Feature(object):
    counter = 0

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

如果您愿意,可以将Feature替换为type(self)(或self.__class__,同样的事情),但请注意,如果存在子类,它们的行为会有所不同(可能这是您的问题) ,实际上)。

在Python中使用类/实例变量的规则非常简单,它有助于牢记这些:

  1. 使用self.name读取属性的值将回退到self类,如果self不直接包含名为{{的属性,则返回到基类层次结构1}}。
  2. 使用name 创建属性的值始终 直接在self.name = ...中绑定name
  3. 特别是,当写一个值时,它并不重要在分配之前对相同属性的读取就已经消失了。

    因此,如果在您的实际程序中,您正在实例化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__.attributeClassName.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