7

スーパークラスからクラス属性を継承し、後でサブクラスの値を変更するとうまくいきます。

class Unit(object):
    value = 10

class Archer(Unit):
    pass

print Unit.value
print Archer.value

Archer.value = 5

print Unit.value
print Archer.value

出力につながります:
10
10
10
5
これは問題ありません: Archer は Unit から値を継承しますが、Archer の値を変更すると、Unit の値は変更されません。

継承された値がリストの場合、浅いコピー効果が発生し、スーパークラスの値も影響を受けます。

class Unit(object):
    listvalue = [10]

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

出力:
10
10
5
5

スーパークラスからリストを継承するときにリストを「ディープコピー」する方法はありますか?


佐野さんありがとうございました

4

3 に答える 3

15

これは浅いコピーや深いコピーの問題ではなく、参照と代入の問題です。

これは最初のケースUnit.valueArcher.value、同じ値を参照する 2 つの変数です。するとArcher.value = 5、Acher.value に新しい参照が割り当てられます。

問題を解決するには、新しいリスト値を に割り当てる必要がありますArcher.list

これらの値がクラス メソッドによってのみアクセスされる場合、最も簡単な解決策は、クラスの初期化時に割り当てを行うことです。

于 2010-03-21T19:13:49.723 に答える
8

Michaelの答えは素晴らしくて単純ですが、その行を各Unitサブクラスに追加する必要がない場合は、そのような他のリストがたくさんある場合は、メタクラスが問題を解決する簡単な方法です。

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        self.listvalue = [10]

class Unit(object):
    __metaclass__ = UnitMeta
    pass

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

出力:

[10]
[10]
[10]
[5]

この同じアイデアを拡張して、Unitで定義されたリスト(およびdict)を自動的に検索してコピーすることもできます。

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        for superclass in self.__mro__:
            for k,v in vars(superclass).items():
                if isinstance(v, (list, dict, )):
                    setattr(self, k, type(v)(v))

class Unit(object):
    __metaclass__ = UnitMeta
    listvalue = [10]

class Archer(Unit):
    pass
于 2010-03-21T20:34:17.033 に答える
0

Archer の定義のリストをコピーできます。

class Archer(Unit):
    listvalue = Unit.listvalue[:]
于 2010-03-21T19:14:33.760 に答える