0

特定のクラス用に作成されたすべてのインスタンスのカウンターを作成しようとしています。私のコードが 1 を超えてインクリメントしないことは明らかですself.__class__.counter。何が間違っていますか?

 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

Feature必要に応じてtype(self)(または、同じもの) に置き換えることができself.__class__ますが、サブクラスが存在する場合は動作が異なることに注意してください (実際にはそれが問題なのかもしれません)。

クラス/インスタンス変数を使用するためのルールは、Python では非常に単純であり、覚えておくと役立ちます。

  1. で属性の値を読み取るとself.name、 のクラスにフォールバックし、に という名前の属性が直接含まれていないself場合は基本クラス階層にフォー​​ルバックします。selfname
  2. self.name = ... 属性の値をalwaysで書き込むと、にname直接バインドされselfます。

特に、値を書き込む場合、同じ属性への読み取りが割り当ての前にどこに行ったかは問題ではありません。

したがって、実際のプログラムで のサブクラスをインスタンス化している場合は、次の行Featureを呼び出します。Sub

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

おそらくあなたが期待することをしないでしょう。( のインスタンスを初めて作成するとき)から読み取りますが、 に書き込みます。その後、読み取りが行われるため(現在存在するため)、インスタンスの ID は増加しますが、 の値は増加しないため、 の他のサブクラスのインスタンスは重複した ID を取得できます。Feature.counterSubSub.counterSub.counterSubFeature.counterFeature

したがって、名前空間に存在するグローバル変数としてFeature.counter考えていた場合に使用し、のすべてのサブクラスで同じカウンターを共有したかったのです。のすべてのサブクラスに独自の独立したカウンターがあると予想される場合に使用します(ただし、それらを初期化するために何かをする必要があります)。counterFeatureFeaturetype(self).counterFeature

于 2013-03-18T22:18:29.363 に答える
1

インスタンスを数えようとするとき、私はこのパラダイムをとても好みます:

from itertools import count

class MyClass():
  _getId = count(0).next
  def __init__(self):
    self.id = self._getId()
于 2013-03-18T22:14:34.767 に答える
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
于 2013-03-18T22:10:24.897 に答える
0

のように、クラス名自体を使用しないのはなぜですか

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