Pythonのセット

Pythonのセット

おそらく、数学教育のある時点で*セット*および*セット理論*について学んだことを思い出すでしょう。 ベン図を覚えているかもしれません:

Venn diagram、width = 992、height = 599

これがベルを鳴らさなくても、心配しないでください! このチュートリアルはまだ簡単にアクセスできるはずです。

数学では、集合の厳密な定義は抽象的であり、把握するのが難しい場合があります。 実際には、セットは、通常 elements または members と呼ばれる、明確に定義された個別のオブジェクトのコレクションと考えることができます。

オブジェクトをセットにグループ化することは、プログラミングにも役立ちます。Pythonには、そのための組み込みセットタイプが用意されています。 セットは、実行できる一意の操作によって他のオブジェクトタイプと区別されます。

このチュートリアルで学習する内容は次のとおりです。 Pythonで set オブジェクトを定義し、それらがサポートする操作を見つける方法について説明します。 リストとディクショナリに関する以前のチュートリアルと同様に、このチュートリアルを終了すると、セットが適切な選択であるタイミングを十分に把握できます。 また、*凍結セット*についても学びます。これは、1つの重要な詳細を除いてセットに似ています。

  • __クイズに挑戦:*インタラクティブな「Python Sets」クイズで知識をテストします。 完了すると、学習の進捗状況を経時的に追跡できるようにスコアを受け取ります。

link:/quizzes/python-sets/[クイズに挑戦»]

セットの定義

Pythonの組み込みの `+ set +`型には次の特性があります。

  • セットは順不同です。

  • セット要素は一意です。 重複する要素は許可されていません。

  • セット自体は変更できますが、セットに含まれる要素は不変型でなければなりません。

それが何を意味するのか、そしてPythonでセットを操作する方法を見てみましょう。

セットは2つの方法で作成できます。 最初に、組み込みの `+ set()+`関数でセットを定義できます:

x = set(<iter>)

この場合、引数 `+ <iter> `は、セットに含まれるオブジェクトのリストを生成する反復可能な(ここでも、思考リストまたはタプル)ことです。 これは、 ` .extend()`リストメソッドに指定された ` <iter> +`引数に類似しています。

>>>

>>> x = set(['foo', 'bar', 'baz', 'foo', 'qux'])
>>> x
{'qux', 'foo', 'bar', 'baz'}

>>> x = set(('foo', 'bar', 'baz', 'foo', 'qux'))
>>> x
{'qux', 'foo', 'bar', 'baz'}

文字列も反復可能であるため、文字列も `+ set()`に渡すことができます。 ` list(s)`が文字列 ` s `内の文字のリストを生成することは既に見ました。 同様に、 ` set(s)`は ` s +`の文字セットを生成します:

>>>

>>> s = 'quux'

>>> list(s)
['q', 'u', 'u', 'x']
>>> set(s)
{'x', 'u', 'q'}

結果のセットは順序付けられていないことがわかります。定義で指定されている元の順序は、必ずしも保持されません。 さらに、最初の2つの例の文字列 `+ 'foo' `と3番目の文字 ` 'u' +`のように、重複する値はセットで1回だけ表されます。

あるいは、中括弧( + {} +)でセットを定義できます:

x = {<obj>, <obj>, ..., <obj>}

このようにセットが定義されると、反復可能なものであっても、各 + <obj> +`はセットの別個の要素になります。 この動作は、 `+ .append()+ listメソッドの動作に似ています。

したがって、上記のセットも次のように定義できます。

>>>

>>> x = {'foo', 'bar', 'baz', 'foo', 'qux'}
>>> x
{'qux', 'foo', 'bar', 'baz'}

>>> x = {'q', 'u', 'u', 'x'}
>>> x
{'x', 'q', 'u'}

要点をまとめると:

  • `+ set()+`の引数は反復可能です。 セットに配置される要素のリストを生成します。

  • 中かっこ内のオブジェクトは、反復可能であってもそのままセットに配置されます。

これらの2つのセット定義の違いを確認してください。

>>>

>>> {'foo'}
{'foo'}

>>> set('foo')
{'o', 'f'}

セットは空にすることができます。 ただし、Pythonは空の中括弧( + {} +)を空の辞書として解釈するため、空のセットを定義する唯一の方法は `+ set()+`関数を使用することです。

>>>

>>> x = set()
>>> type(x)
<class 'set'>
>>> x
set()

>>> x = {}
>>> type(x)
<class 'dict'>

空のセットはブールコンテキストでは偽です:

>>>

>>> x = set()
>>> bool(x)
False
>>> x or 1
1
>>> x and 1
set()

最も直感的なセットには同様のオブジェクトが含まれていると考えるかもしれません。たとえば、偶数や姓:

>>>

>>> s1 = {2, 4, 6, 8, 10}
>>> s2 = {'Smith', 'McArthur', 'Wilson', 'Johansson'}

ただし、Pythonはこれを必要としません。 セット内の要素は、さまざまなタイプのオブジェクトにすることができます。

>>>

>>> x = {42, 'foo', 3.14159, None}
>>> x
{None, 'foo', 42, 3.14159}

セット要素は不変でなければならないことを忘れないでください。 たとえば、タプルをセットに含めることができます。

>>>

>>> x = {42, 'foo', (1, 2, 3), 3.14159}
>>> x
{42, 'foo', 3.14159, (1, 2, 3)}

ただし、リストと辞書は変更可能であるため、要素を設定することはできません。

>>>

>>> a = [1, 2, 3]
>>> {a}
Traceback (most recent call last):
  File "<pyshell#70>", line 1, in <module>
    {a}
TypeError: unhashable type: 'list'

>>> d = {'a': 1, 'b': 2}
>>> {d}
Traceback (most recent call last):
  File "<pyshell#72>", line 1, in <module>
    {d}
TypeError: unhashable type: 'dict'

サイズとメンバーシップを設定する

`+ len()`関数はセット内の要素の数を返し、 ` in `および ` not in +`演算子を使用してメンバーシップをテストできます。

>>>

>>> x = {'foo', 'bar', 'baz'}

>>> len(x)
3

>>> 'bar' in x
True
>>> 'qux' in x
False

セットでの操作

Pythonの他の複合データ型に使用できる操作の多くは、セットには意味がありません。 たとえば、セットをインデックス化またはスライスすることはできません。 ただし、Pythonは、数学的なセットに対して定義されているhttps://en.wikipedia.org/wiki/Set_(mathematics)#Basic_operations[operations]を一般的に模倣するセットオブジェクトの操作のホスト全体を提供します。

演算子対 方法

すべてではありませんが、ほとんどのPythonの集合演算は、演算子またはメソッドの2つの異なる方法で実行できます。 例として集合和を使用して、これらの演算子とメソッドがどのように機能するかを見てみましょう。

2つのセット、「+ x1 」と「 x2 」を考えると、「 x1 」と「 x2 +」の結合は、いずれかのセットのすべての要素で構成されるセットです。

次の2つのセットを検討してください。

x1 = {'foo', 'bar', 'baz'}
x2 = {'baz', 'qux', 'quux'}

「+ x1 」と「 x2 」の結合は、「 {'foo」、「bar」、「baz」、「qux」、「quux」} + `です。

注意: `+ x1 `と ` x2 `の両方に現れる要素 ` 'baz' +`は、ユニオンに1回だけ現れることに注意してください。 セットに重複した値が含まれることはありません。

Pythonでは、 `+ | +`演算子を使用して集合の和集合を実行できます。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}
>>> x1 | x2
{'baz', 'quux', 'qux', 'bar', 'foo'}

set unionは、 `+ .union()+`メソッドでも取得できます。 メソッドはセットの1つで呼び出され、もう1つは引数として渡されます。

>>>

>>> x1.union(x2)
{'baz', 'quux', 'qux', 'bar', 'foo'}

上記の例で使用されている方法、演算子とメソッドは同じように動作します。 しかし、それらの間には微妙な違いがあります。 `+ | `演算子を使用する場合、両方のオペランドを設定する必要があります。 一方、 ` .union()+`メソッドは、イテレート可能なものを引数として受け取り、それをセットに変換してから、ユニオンを実行します。

次の2つのステートメントの違いを確認してください。

>>>

>>> x1 | ('baz', 'qux', 'quux')
Traceback (most recent call last):
  File "<pyshell#43>", line 1, in <module>
    x1 | ('baz', 'qux', 'quux')
TypeError: unsupported operand type(s) for |: 'set' and 'tuple'

>>> x1.union(('baz', 'qux', 'quux'))
{'baz', 'quux', 'qux', 'bar', 'foo'}

どちらも、 `+ x1 `とタプル `( 'baz'、 'qux'、 'quux')`の和集合を計算しようとします。 これは ` | `演算子では失敗しますが、 ` .union()+`メソッドでは成功します。

利用可能な演算子とメソッド

以下は、Pythonで使用可能な集合演算のリストです。 オペレータによって実行されるもの、メソッドによって実行されるもの、および両方によって実行されるものがあります。 上記で概説した原則は一般に適用されます。セットが期待される場合、メソッドは通常、引数として反復可能なものを受け入れますが、演算子はオペランドとして実際のセットを必要とします。

+ x1.union(x2 [、x3 …​])+

`+ x1 | x2 [| x3 …​] + `

_ 2つ以上のセットの和集合を計算します。 _

+ x1.union(x2)+`および `+ x1 | x2 + `は両方とも + x1 + または + x2 + `のすべての要素のセットを返します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

>>> x1.union(x2)
{'foo', 'qux', 'quux', 'baz', 'bar'}

>>> x1 | x2
{'foo', 'qux', 'quux', 'baz', 'bar'}

演算子またはメソッドを使用して、3つ以上のセットを指定できます。

>>>

>>> a = {1, 2, 3, 4}
>>> b = {2, 3, 4, 5}
>>> c = {3, 4, 5, 6}
>>> d = {4, 5, 6, 7}

>>> a.union(b, c, d)
{1, 2, 3, 4, 5, 6, 7}

>>> a | b | c | d
{1, 2, 3, 4, 5, 6, 7}

結果のセットには、指定されたセットのいずれかに存在するすべての要素が含まれます。

+ x1.intersection(x2 [、x3 …​])+

+ x1&x2 [&x3 …​] +

_ 2つ以上のセットの共通部分を計算します。 _

`+ x1.intersection(x2)`と ` x1&x2 `は、 ` x1 `と ` x2 +`の両方に共通する要素のセットを返します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

>>> x1.intersection(x2)
{'baz'}

>>> x1 & x2
{'baz'}

set unionと同様に、intersectionメソッドと演算子で複数のセットを指定できます。

>>>

>>> a = {1, 2, 3, 4}
>>> b = {2, 3, 4, 5}
>>> c = {3, 4, 5, 6}
>>> d = {4, 5, 6, 7}

>>> a.intersection(b, c, d)
{4}

>>> a & b & c & d
{4}

結果のセットには、指定されたすべてのセットに存在する要素のみが含まれます。

+ x1.difference(x2 [、x3 …​])+

+ x1-x2 [-x3 …​] +

_ 2つ以上のセットの差を計算します。 _

「+ x1.difference(x2)」および「 x1-x2 」は、「 x1 」に含まれるが「 x2 +」には含まれないすべての要素のセットを返します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

>>> x1.difference(x2)
{'foo', 'bar'}

>>> x1 - x2
{'foo', 'bar'}

これを考える別の方法は、「+ x1.difference(x2)」と「 x1-x2 」が、「 x2 」の要素が「 x1 +」から削除または減算された結果のセットを返すことです。

ここでも、3つ以上のセットを指定できます。

>>>

>>> a = {1, 2, 3, 30, 300}
>>> b = {10, 20, 30, 40}
>>> c = {100, 200, 300, 400}

>>> a.difference(b, c)
{1, 2, 3}

>>> a - b - c
{1, 2, 3}

複数のセットが指定されている場合、操作は左から右に実行されます。 上記の例では、 `+ a-b `が最初に計算され、 ` {1、2、3、300} `になります。 次に、そのセットから「 c 」が減算され、「 {1、2、3} +」が残ります。

set difference、multiple sets、width = 2307、height = 993

+ x1.symmetric_difference(x2)+

+ x1 ^ x2 [^ x3 …​] +

_ セット間のhttps://en.wikipedia.org/wiki/Symmetric_difference [対称差]を計算します。 _

`+ x1.symmetric_difference(x2)`および ` x1 ^ x2 `は、両方ではなく、 ` x1 `または ` x2 +`のすべての要素のセットを返します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

>>> x1.symmetric_difference(x2)
{'foo', 'qux', 'quux', 'bar'}

>>> x1 ^ x2
{'foo', 'qux', 'quux', 'bar'}

`+ ^ +`演算子は3つ以上のセットも許可します:

>>>

>>> a = {1, 2, 3, 4, 5}
>>> b = {10, 2, 3, 4, 50}
>>> c = {1, 50, 100}

>>> a ^ b ^ c
{100, 5, 10}

差分演算子と同様に、複数のセットが指定されている場合、操作は左から右に実行されます。

奇妙なことに、 `+ ^ `演算子は複数のセットを許可しますが、 ` .symmetric_difference()+`メソッドは次のことを行いません。

>>>

>>> a = {1, 2, 3, 4, 5}
>>> b = {10, 2, 3, 4, 50}
>>> c = {1, 50, 100}

>>> a.symmetric_difference(b, c)
Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    a.symmetric_difference(b, c)
TypeError: symmetric_difference() takes exactly one argument (2 given)

+ x1.isdisjoint(x2)+

_ 2つのセットに共通の要素があるかどうかを決定します。 _

「+ x1.isdisjoint(x2)」は、「 x1 」と「 x2 」に共通の要素がない場合、「 True +」を返します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

>>> x1.isdisjoint(x2)
False

>>> x2 - {'baz'}
{'quux', 'qux'}
>>> x1.isdisjoint(x2 - {'baz'})
True

`+ x1.isdisjoint(x2)`が ` True `の場合、 ` x1&x2 +`は空のセットです。

>>>

>>> x1 = {1, 3, 5}
>>> x2 = {2, 4, 6}

>>> x1.isdisjoint(x2)
True
>>> x1 & x2
set()

注意: `+ .isdisjoint()+`メソッドに対応する演算子はありません。

+ x1.issubset(x2)+

+ x1 ⇐ x2 +

_ 1つのセットが他のセットのサブセットであるかどうかを判別します。 _

セット理論では、「+ x1 」のすべての要素が「 x2 」にある場合、セット「 x1 」は別のセット「 x2 +」のサブセットと見なされます。

`+ x1 `が ` x2 `のサブセットである場合、 ` x1.issubset(x2)`および ` x1 ⇐ x2 `は ` True +`を返します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x1.issubset({'foo', 'bar', 'baz', 'qux', 'quux'})
True

>>> x2 = {'baz', 'qux', 'quux'}
>>> x1 <= x2
False

セットはそれ自体のサブセットと見なされます。

>>>

>>> x = {1, 2, 3, 4, 5}
>>> x.issubset(x)
True
>>> x <= x
True

おそらく奇妙に思えます。 しかし、それは定義に適合しています。+ x + `のすべての要素は + x + `にあります。

+ x1 <x2 +

_ 1つのセットが他のセットの適切なサブセットであるかどうかを判別します。 _

適切なサブセットはサブセットと同じですが、セットを同一にすることはできません。 「+ x1 」のすべての要素が「 x2 」にあり、「 x1 」と「 x2 」が等しくない場合、セット「 x1 」は別のセット「 x2 +」の適切なサブセットと見なされます。

「+ x1 <x2 」は、「 x1 」が「 x2 」の適切なサブセットである場合、「 True +」を返します。

>>>

>>> x1 = {'foo', 'bar'}
>>> x2 = {'foo', 'bar', 'baz'}
>>> x1 < x2
True

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'bar', 'baz'}
>>> x1 < x2
False

セットはそれ自体のサブセットと見なされますが、それ自体の適切なサブセットではありません。

>>>

>>> x = {1, 2, 3, 4, 5}
>>> x <= x
True
>>> x < x
False

注意: `+ <+`演算子は、セットが適切なサブセットであるかどうかをテストする唯一の方法です。 対応する方法はありません。

+ x1.issuperset(x2)+

+ x1> = x2 +

_ 1つのセットが他のセットのスーパーセットであるかどうかを判別します。 _

スーパーセットは、サブセットの逆です。 「+ x1 」が「 x2 」のすべての要素を含む場合、セット「 x1 」は別のセット「 x2 +」のスーパーセットと見なされます。

`+ x1 `が ` x2 `のスーパーセットである場合、 ` x1.issuperset(x2)`および ` x1> = x2 `は ` True +`を返します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}

>>> x1.issuperset({'foo', 'bar'})
True

>>> x2 = {'baz', 'qux', 'quux'}
>>> x1 >= x2
False

セットはそれ自体のサブセットと見なされることを既に見ました。 セットは、それ自体のスーパーセットとも見なされます。

>>>

>>> x = {1, 2, 3, 4, 5}
>>> x.issuperset(x)
True
>>> x >= x
True

+ x1> x2 +

_ 1つのセットが他のセットの適切なスーパーセットであるかどうかを判別します。 _

適切なスーパーセットはスーパーセットと同じですが、セットを同一にすることはできません。 セット「+ x1 」は、「 x1 」が「 x2 」のすべての要素を含み、「 x1 」と「 x2 」が等しくない場合、別のセット「 x2 +」の適切なスーパーセットと見なされます。

`+ x1 `が ` x2 `の適切なスーパーセットである場合、 ` x1> x2 `は ` True +`を返します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'bar'}
>>> x1 > x2
True

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'bar', 'baz'}
>>> x1 > x2
False

セットはそれ自体の適切なスーパーセットではありません。

>>>

>>> x = {1, 2, 3, 4, 5}
>>> x > x
False

注意: `+> +`演算子は、セットが適切なスーパーセットであるかどうかをテストする唯一の方法です。 対応する方法はありません。

セットの変更

セットに含まれる要素は不変型でなければなりませんが、セット自体は変更できます。 上記の操作と同様に、セットの内容を変更するために使用できる演算子とメソッドが混在しています。

拡張割り当て演算子とメソッド

上記の共用体、交差、差、および対称差演算子のそれぞれには、セットを変更するために使用できる拡張割り当て形式があります。 それぞれに対応する方法もあります。

+ x1.update(x2 [、x3 …​])+

`+ x1 | = x2 [| x3 …​] + `

_ 集合ごとにセットを変更します。 _

`+ x1.update(x2)`と ` x1 | = x2 `は、 ` x1 `がまだ持っていない ` x2 `の要素を ` x1 +`に追加します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'baz', 'qux'}

>>> x1 |= x2
>>> x1
{'qux', 'foo', 'bar', 'baz'}

>>> x1.update(['corge', 'garply'])
>>> x1
{'qux', 'corge', 'garply', 'foo', 'bar', 'baz'}

+ x1.intersection_update(x2 [、x3 …​])+

+ x1&= x2 [&x3 …​] +

_ 交差によってセットを変更します。 _

`+ x1.intersection_update(x2)`と ` x1&= x2 `は ` x1 `を更新し、 ` x1 `と ` x2 +`の両方で見つかった要素のみを保持します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'baz', 'qux'}

>>> x1 &= x2
>>> x1
{'foo', 'baz'}

>>> x1.intersection_update(['baz', 'qux'])
>>> x1
{'baz'}

+ x1.difference_update(x2 [、x3 …​])+

`+ x1-= x2 [| x3 …​] + `

_ 違いによってセットを変更します。 _

`+ x1.difference_update(x2)`および ` x1-= x2 `は ` x1 `を更新し、 ` x2 +`で見つかった要素を削除します。

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'baz', 'qux'}

>>> x1 -= x2
>>> x1
{'bar'}

>>> x1.difference_update(['foo', 'bar', 'qux'])
>>> x1
set()

+ x1.symmetric_difference_update(x2)+

+ x1 ^ = x2 +

_ 対称差によりセットを変更します。 _

`+ x1.symmetric_difference_update(x2)`および ` x1 ^ = x2 `は ` x1 `を更新し、 ` x1 `または ` x2 +`のいずれかで見つかった要素を保持しますが、両方ではありません:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'baz', 'qux'}
>>>
>>> x1 ^= x2
>>> x1
{'bar', 'qux'}
>>>
>>> x1.symmetric_difference_update(['qux', 'corge'])
>>> x1
{'bar', 'corge'}

セットを変更する他の方法

上記の拡張演算子とは別に、Pythonはセットを変更するいくつかの追加メソッドをサポートしています。

+ x.add(<elem>)+

_ セットに要素を追加します。 _

`+ x.add(<elem>)`は、単一の不変オブジェクトでなければならない ` <elem> `を ` x +`に追加します。

>>>

>>> x = {'foo', 'bar', 'baz'}

>>> x.add('qux')
>>> x
{'bar', 'baz', 'foo', 'qux'}

+ x.remove(<elem>)+

_ セットから要素を削除します。 _

`+ x.remove(<elem>)`は、 ` x `から ` <elem> `を削除します。 ` <elem> `が ` x +`にない場合、Pythonは例外を発生させます:

>>>

>>> x = {'foo', 'bar', 'baz'}

>>> x.remove('baz')
>>> x
{'bar', 'foo'}

>>> x.remove('qux')
Traceback (most recent call last):
  File "<pyshell#58>", line 1, in <module>
    x.remove('qux')
KeyError: 'qux'

+ x.discard(<elem>)+

_ セットから要素を削除します。 _

`+ x.discard(<elem>)`は、 ` x `から ` <elem> `も削除します。 しかし、 ` <elem> `が ` x +`にない場合、このメソッドは例外を発生させる代わりに静かに何もしません:

>>>

>>> x = {'foo', 'bar', 'baz'}

>>> x.discard('baz')
>>> x
{'bar', 'foo'}

>>> x.discard('qux')
>>> x
{'bar', 'foo'}

+ x.pop()+

_ セットからランダムな要素を削除します。 _

`+ x.pop()`は、 ` x `から任意に選択した要素を削除して返します。 ` x `が空の場合、 ` x.pop()+`は例外を発生させます:

>>>

>>> x = {'foo', 'bar', 'baz'}

>>> x.pop()
'bar'
>>> x
{'baz', 'foo'}

>>> x.pop()
'baz'
>>> x
{'foo'}

>>> x.pop()
'foo'
>>> x
set()

>>> x.pop()
Traceback (most recent call last):
  File "<pyshell#82>", line 1, in <module>
    x.pop()
KeyError: 'pop from an empty set'

+ x.clear()+

_ セットをクリアします。 _

`+ x.clear()`は、すべての要素を ` x +`から削除します。

>>>

>>> x = {'foo', 'bar', 'baz'}
>>> x
{'foo', 'bar', 'baz'}
>>>
>>> x.clear()
>>> x
set()

冷凍セット

Pythonは、 frozenset と呼ばれる別の組み込み型を提供します。これは、すべての点において、frozensetが不変であることを除いて、すべての点でsetとまったく同じです。 frozensetで非変更操作を実行できます。

>>>

>>> x = frozenset(['foo', 'bar', 'baz'])
>>> x
frozenset({'foo', 'baz', 'bar'})

>>> len(x)
3

>>> x & {'baz', 'qux', 'quux'}
frozenset({'baz'})

ただし、frozensetを変更しようとするメソッドは失敗します。

>>>

>>> x = frozenset(['foo', 'bar', 'baz'])

>>> x.add('qux')
Traceback (most recent call last):
  File "<pyshell#127>", line 1, in <module>
    x.add('qux')
AttributeError: 'frozenset' object has no attribute 'add'

>>> x.pop()
Traceback (most recent call last):
  File "<pyshell#129>", line 1, in <module>
    x.pop()
AttributeError: 'frozenset' object has no attribute 'pop'

>>> x.clear()
Traceback (most recent call last):
  File "<pyshell#131>", line 1, in <module>
    x.clear()
AttributeError: 'frozenset' object has no attribute 'clear'

>>> x
frozenset({'foo', 'bar', 'baz'})

_ _ ディープダイブ:凍結セットと拡張割り当て

frozensetは不変であるため、拡張代入演算子のターゲットにできないと考えるかもしれません。 ただし、次の点に注意してください。

>>>

>>> f = frozenset(['foo', 'bar', 'baz'])
>>> s = {'baz', 'qux', 'quux'}

>>> f &= s
>>> f
frozenset({'baz'})

何ができる?

Pythonは、所定の場所にあるfrozensetに対して拡張割り当てを実行しません。 ステートメント `+ x&= s `は、実質的に ` x = x&s `と同等です。 元の「 x 」を変更するわけではありません。 新しいオブジェクトに ` x `を再割り当てし、元々参照されていたオブジェクト ` x +`はなくなりました。

これは `+ id()+`関数で確認できます:

>>>

>>> f = frozenset(['foo', 'bar', 'baz'])
>>> id(f)
56992872
>>> s = {'baz', 'qux', 'quux'}

>>> f &= s
>>> f
frozenset({'baz'})
>>> id(f)
56992152

`+ f +`には、拡張された割り当てに続く異なる整数識別子があります。 その場所は変更されておらず、再割り当てされています。

Pythonの一部のオブジェクトは、拡張代入演算子のターゲットである場合、その場で変更されます。 しかし、frozensetsはそうではありません。 _ _

凍結セットは、セットを使用したいが、不変オブジェクトが必要な状況で役立ちます。 たとえば、セット要素は不変でなければならないため、要素もセットであるセットを定義することはできません。

>>>

>>> x1 = set(['foo'])
>>> x2 = set(['bar'])
>>> x3 = set(['baz'])
>>> x = {x1, x2, x3}
Traceback (most recent call last):
  File "<pyshell#38>", line 1, in <module>
    x = {x1, x2, x3}
TypeError: unhashable type: 'set'

セットのセットを定義することを本当に強いられていると感じた場合(そうなる可能性があります)、要素が不変であるため、要素がfrozensetである場合、それを行うことができます。

>>>

>>> x1 = frozenset(['foo'])
>>> x2 = frozenset(['bar'])
>>> x3 = frozenset(['baz'])
>>> x = {x1, x2, x3}
>>> x
{frozenset({'bar'}), frozenset({'baz'}), frozenset({'foo'})}

同様に、前のhttps://realpython.com/python-dicts[dictionaries]のチュートリアルから、辞書キーは不変でなければならないことを思い出してください。 組み込みのセットタイプを辞書キーとして使用することはできません。

>>>

>>> x = {1, 2, 3}
>>> y = {'a', 'b', 'c'}
>>>
>>> d = {x: 'foo', y: 'bar'}
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    d = {x: 'foo', y: 'bar'}
TypeError: unhashable type: 'set'

セットを辞書キーとして使用する必要がある場合は、frozensetsを使用できます。

>>>

>>> x = frozenset({1, 2, 3})
>>> y = frozenset({'a', 'b', 'c'})
>>>
>>> d = {x: 'foo', y: 'bar'}
>>> d
{frozenset({1, 2, 3}): 'foo', frozenset({'c', 'a', 'b'}): 'bar'}

結論

このチュートリアルでは、Pythonで set オブジェクトを定義する方法を学び、セットの操作に使用できる関数、演算子、およびメソッドに精通しました。

これで、Pythonが提供する基本的な組み込みデータ型に慣れるはずです。

次に、これらのオブジェクトで動作するコードが、Pythonプログラムでどのように編成および構造化されているかを探り始めます。

  • __クイズに挑戦:*インタラクティブな「Python Sets」クイズで知識をテストします。 完了すると、学習の進捗状況を経時的に追跡できるようにスコアを受け取ります。

link:/quizzes/python-sets/[クイズに挑戦»]