1

Python でクラス属性について話すときの一般的な例は次のとおりです。

Python 2.7.6 (default, Sep 9 2014, 15:04:36)
>>> class B(object):
... cv = []
...
>>> b1 = B()
>>> b2 = B()
>>> b1.cv, b2.cv, B.cv
([], [], [])
>>> b1.cv.append(1)
>>> b1.cv, b2.cv, B.cv
([1], [1], [1])
>>> b2.cv.append(2)
>>> b1.cv, b2.cv, B.cv
([1, 2], [1, 2], [1, 2])
>>> B.cv.append(3)
>>> b1.cv, b2.cv, B.cv
([1, 2, 3], [1, 2, 3], [1, 2, 3])

クラス属性がクラスとそのすべてのインスタンス間で共有されていることを示しています。

しかし、クラス属性の値を再代入すると、つまり、クラス属性にバインドされた初期オブジェクトを変更しないと、次のようになります。

>>> class A(object):
... cv = 0
...
>>> a1 = A()
>>> a2 = A()
>>> a1.cv, a2.cv, A.cv
(0, 0, 0)
>>> a1.cv = 1
>>> a1.cv, a2.cv, A.cv
(1, 0, 0)
>>> a2.cv = 2
>>> a1.cv, a2.cv, A.cv
(1, 2, 0)
>>> A.cv = 3
>>> a1.cv, a2.cv, A.cv
(1, 2, 3)

ここで、このクラス属性が一意の値を格納するたびに、インスタンスとクラスの両方の名前空間に適用される次の割り当てでオーバーライドされないことがわかります。

なぜこのような振る舞いになるのでしょうか。

「不変」(A)および「可変」(B)の場合に「関連性のない」動作につながるこのロジックがどのようなものなのか理解できません。これにより、「使用する意味がない」と思いますクラス変数」は間違いを起こしやすいので...

このトンネルに光が見えないのは私だといいのですが…

4

3 に答える 3

2

最初の例では、リストを変更します。ユニバースには、リストのインスタンスが 1 つしかありませんB.__dict__['cv']。2 番目の例では、値を割り当てます。これを行うと、それぞれの特定のインスタンスで割り当てが行われます。これはa(1|2|3)、Python で属性設定がどのように機能するかによるものです (__dict__属性を変更しようとしているものの に保存されます)。A.cvすべてを変更するには変更する必要があり、 で行っa(1|2|3)た変更は行った変更を上書きします。

(Python は使用を試みa(1|2|3).__dict__、その後 にフォールバックしA.__dict__ます。)

于 2015-03-07T19:29:04.847 に答える
1

Chris Warrick による答えを説明するもう 1 つの最後の例

>>> A.cv = 0
>>> a1, a2 = A(), A()
>>> A.cv, a1.cv, a2.cv
(0, 0, 0)
>>> A.cv = 1
>>> A.cv, a1.cv, a2.cv
(1, 1, 1)
>>> a1.cv = 2   # Here the new instance attribute is created for a1, 
# and so it will hide the class attribute with the same name, 
# once getting the value from instance namespace
>>> A.cv, a1.cv, a2.cv
(1, 2, 1)
>>> A.cv = 3
>>> A.cv, a1.cv, a2.cv
(3, 2, 3)
于 2015-03-07T19:34:55.047 に答える
0

インスタンスを介してクラス属性を使用するつもりがない場合は、クラス属性を効果的に使用できます。たとえば、クラス属性で同じクラスのオブジェクトのグループを管理するのが好きです。Pygame について聞いたことがあるなら、私はこの手法を最も頻繁に使用する傾向があります。

class Alien:
    sprites = []

    def __init__(self, x, y):
        self.surf = pygame.image.load('Alien.png')
        self.rect = self.surf.get_rect()

        self.rect.topleft = (x, y)
        Alien.sprites.append(self)

    @staticmethod
    def draw_sprites(screen):
        for sprite in Alien.sprites:
            screen.blit(sprite.surf, sprite.rect)

クラス メソッドと属性を使用すると、オブジェクト管理がこれほど簡単になることがわかりますか?

于 2015-03-08T00:29:31.047 に答える