a
クラスではmy_hand
、変数はすべてクラス属性 (つまりother_hand
、静的属性) であり、インスタンス属性ではありません。hands
また、メソッドでandclear
を再割り当てしますが、古いs を引き続き参照するため、その内容は変更されません。python3 を使用している場合は、 s:およびのメソッドを使用する必要があります。その後、2 つの空の が参照されます。python2 で行う必要があります。my_hand
other_hand
hands
list
clear()
list
my_hand.clear()
other_hand.clear()
hands
list
del my_hand[:]
インスタンス属性を割り当てたい場合は、する必要がありますself.attribute = value
。そのためには__init__
、クラスのコンストラクターであるメソッド内に割り当てを配置する必要があります。
現在のコードでは、 の 2 つのインスタンスを作成するとa
、それらはハンドを共有します。これはおそらく望ましくないことです。
正しいコードは次のようになります。
import random
class ClassesUseCamelCase(object):
# if you are using python2 do *not* forget to inherit object.
def __init__(self):
self.my_hand = []
self.other_hand = []
self.hands = [self.my_hand, self.other_hand]
def init_hands(self):
for round in range(5):
for hand in self.hands:
hand.append(round)
# or simpler:
# for hand in self.hands:
# hand.extend(range(5))
def shuffle(self):
random.shuffle(self.my_hand)
random.shuffle(self.other_hand)
def clear(self):
self.my_hand.clear() # or del self.my_hand[:] in python2
self.other_hand.clear()
iPython を使用したサンプル出力:
In [2]: inst = ClassesUseCamelCase()
In [3]: inst.init_hands()
In [4]: inst.shuffle()
In [5]: inst.hands
Out[5]: [[3, 2, 4, 0, 1], [3, 1, 4, 0, 2]]
In [6]: inst.clear()
In [7]: inst.hands
Out[7]: [[], []]
複数のインスタンスで機能することに注意してください。
In [9]: inst.init_hands()
In [10]: other = ClassesUseCamelCase()
In [11]: other.init_hands()
In [12]: inst.hands, other.hands
Out[12]: ([[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]], [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]])
In [13]: inst.shuffle(); other.shuffle()
...:
In [14]: inst.hands
Out[14]: [[0, 1, 3, 2, 4], [1, 4, 0, 3, 2]]
In [15]: other.hands
Out[15]: [[1, 4, 2, 0, 3], [1, 4, 3, 2, 0]]
hands
コードは2 つのインスタンス間で共有されます。
コメントを書きすぎないように、何が起こっているのかについてもう少し説明を加えます。
まず第一に、あなたのコードではmy_hand
とother_hand
はクラス属性です。なぜこれが重要なのですか?クラス属性はインスタンス間で共有されるため、これは重要です:
In [1]: class MyClass(object):
...: my_hand = []
...: other_hand = []
...: hands = [my_hand, other_hand]
...:
In [2]: instance_one = MyClass()
In [3]: instance_two = MyClass()
In [4]: instance_one.my_hand.append(1)
In [5]: instance_two.my_hand # ops!
Out[5]: [1]
を呼び出すとclear
、クラス属性が変更されるため、それらを使用するすべてのインスタンスが変更されます。これは通常、望ましくないことです。
インスタンスには他のインスタンス属性がありません。これは、実際にはすべてのインスタンスが等しいことを意味します。それらはすべて同じように機能し、同じデータを提供します。唯一の違いは、彼らのアイデンティティです。ID を使用しない場合、クラスと複数のインスタンスを持つことは、単純に 1 つのオブジェクトを使用することができたので、意味がありません。
インスタンスに、他のインスタンスのデータから独立した独自のデータを持たせたい場合は、インスタンス属性を使用する必要があります。
del
声明について。コメントで既に述べたように、del
2 つの異なる用途があります。ステートメントの完全な構文は次のとおりです。
del sequence, of, del_targets
ここで、「sequence, of, del_targets」は、私が呼ぶもののカンマ区切りのリストですdel_targets
。によってdel_target
挙動が変わります。
それが識別子である場合、スコープからその参照del
を削除し、識別子によって参照されたオブジェクトの参照カウントを減らします。
例えば:
a = b = []
# Now that empty list has two references: a and b
del b # now it has only one reference: a
print(b) # This raises a NameError because b doesn't exist anymore
del a # Now the empty list doesn't have references
オブジェクトに参照がない場合は破棄されるため、del a
上記の後、空のリストはインタープリターによって破棄されます。
ターゲットは、「添え字」、つまりname[key-or-index]
or name[a:slice]
(or name[start:stop:step]
) のような式にすることもできます。スライス構文 (コロン付きのもの) は、インデックスの範囲を指定するために使用されます。
In [17]: numbers = list(range(10)) # [0, 1, ..., 9]
In [18]: numbers[::2], numbers[1::2], numbers[2:7:3]
Out[18]: ([0, 2, 4, 6, 8], [1, 3, 5, 7, 9], [2, 5])
del
このような式でステートメントを使用すると、python は__delitem__
オブジェクトのメソッドを呼び出し、インデックスまたはスライスを渡します。この意味は:
del numbers[:]
numbers
手段:スライス内のインデックスに対応するリストのすべての要素を削除します:
。スライス:
は「シーケンス内のすべてのインデックス」を意味するため、結果はリストを空にします。リストから参照が削除されないことに注意してください。それはその要素にのみ作用します。
以下を使用して同じ効果を得ることができます。
numbers[:] = []
これは、スライス:
に対応する要素のシーケンスを の要素に置き換えるように python に指示し[]
ます。:
は「すべての要素」を意味し、空であるため[]
、効果はリストからすべての要素を削除することです。この構文は内部ではlist.__setitem__
なく呼び出しますlist.__delitem__
が、結果は同じです。ただし、次のこともできます。numbers[:] = [2]
その後、 のすべての要素numbers
が削除され、が2
挿入されて list になります[2]
。
どちらも機能しdel
ますが、意図を明確にするため、構文を好みます。あなたが読むとき:
del something[:]
ステートメントが何かを削除しようとしていることがわかります。次に、下付き文字を見て、参照ではなく[:]
から要素を削除することを理解します。ただし、次の場合:something
something
something[:] = []
まず、これは課題だと思います。次に が表示[:]
され、リストの内容を「上書き」しようとしていることがわかります。次に、右側を見て を見て[]
、要素を空のリストで上書きします...最終的に、ステートメントがリストからすべての要素を単純に削除することがわかります。