2.10. Set#

Sebuah set adalah koleksi item unik yang tidak terurut. Menambahkan nilai yang sudah ada tidak berpengaruh; iterasi menghasilkan setiap nilai tepat satu kali. Set adalah alat yang tepat ketika keanggotaan dan penghapusan duplikat penting, dan urutan tidak penting.

2.10.1. Membuat set#

Gunakan kurung kurawal untuk set yang tidak kosong, atau set() untuk yang kosong:

colours = {"red", "green", "blue"}
empty = set()

Kurung kurawal terlihat seperti literal dict; {} sendiri adalah dict kosong, bukan set kosong -- salah satu kecelakaan historis Python. Gunakan set() untuk kasus kosong.

set() juga membangun set dari iterable apa pun, yang merupakan cara standar untuk menghapus duplikat dari sebuah urutan:

nums = [1, 2, 2, 3, 1, 4]
unique = set(nums)
print(unique)

Output:

{1, 2, 3, 4}

Urutan print mungkin bervariasi -- set tidak menjanjikan iterasi dalam urutan tertentu.

2.10.2. Set vs dict#

Set dan dict keduanya menyimpan item unik dalam tabel hash. Perbedaannya adalah apa yang dibawa setiap item:

  • dict menyimpan pasangan kunci-nilai. Mencari kunci mengembalikan nilainya.

  • set menyimpan hanya item tersebut. Mencari item memberitahu Anda apakah item tersebut ada.

Pilihan antara keduanya bergantung pada apakah nilai di samping setiap item bermakna:

  • Gunakan set ketika tidak ada nilai yang perlu disandingkan dengan setiap item -- Anda hanya peduli apakah item tersebut ada, atau Anda menggabungkan grup item unik dengan union / intersection.

  • Gunakan dict ketika setiap item dipasangkan dengan data yang ingin diambil oleh pencarian -- peta konfigurasi, cache, penghitung berdasarkan nama.

Kedua tipe berbagi banyak sintaks permukaan, yang menjadi sumber kebingungan terbesar. Perbedaannya dalam satu blok:

set

dict

menampung

item unik

kunci unik, masing-masing dengan nilai

literal terisi

{1, 2, 3}

{"a": 1, "b": 2}

literal kosong

set()

{}

uji keanggotaan

x in s

k in d (hanya kunci)

ambil nilai

n/a

d[k]

tambah item

s.add(x)

d[k] = v

iterasi

menghasilkan item

menghasilkan kunci (gunakan d.items() untuk pasangan)

Asimetri antara literal terisi dan literal kosong adalah hal yang perlu diperhatikan:

  • Kurung kurawal dengan item di dalamnya -- {1, 2, 3} -- adalah literal set; kurung kurawal dengan pasangan kunci-nilai -- {"a": 1} -- adalah literal dict. Parser membedakannya berdasarkan apa yang ada di dalamnya.

  • Kurung kurawal dengan tidak ada di dalamnya -- {} -- adalah dict kosong, bukan set kosong. Dict hadir lebih dulu; literal kosong milik mereka. Set kosong tidak memiliki literal kurung kurawal sama sekali dan harus ditulis set().

Pola umum ketika hanya kunci dict yang pernah dibaca adalah beralih ke set -- ini membuat maksudnya jelas dan menghapus nilai yang tidak terpakai dari memori.

2.10.3. Menambah dan menghapus#

s = {1, 2, 3}
s.add(4)
s.discard(99)            # silent: 99 not in s
s.remove(2)
print(s)

Output:

{1, 3, 4}

2.10.4. Keanggotaan#

Operator in menguji keanggotaan. Pada set, operasi ini kurang lebih konstan waktunya terlepas dari ukurannya -- yang merupakan alasan utama untuk memilih set daripada list ketika Anda hanya perlu bertanya "apakah nilai ini ada di sini":

if "red" in colours:
    print("colour is allowed")

list dengan isi yang sama akan memindai dari awal setiap kali, yang baik-baik saja untuk sepuluh item tetapi lambat untuk sepuluh ribu.

2.10.5. Operasi set#

Dua set dapat digabungkan dengan operasi matematika biasa. Masing-masing memiliki bentuk operator dan bentuk metode:

  • a | b atau a.union(b) -- semua yang ada di salah satu set.

  • a & b atau a.intersection(b) -- hanya yang muncul di keduanya.

  • a - b atau a.difference(b) -- ada di a tapi tidak di b.

  • a ^ b atau a.symmetric_difference(b) -- ada di satu tapi tidak keduanya.

a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b)
print(a & b)
print(a - b)
print(a ^ b)

Output:

{1, 2, 3, 4, 5, 6}
{3, 4}
{1, 2}
{1, 2, 5, 6}

Bentuk operator bersifat read-only; bentuk metode menerima iterable apa pun di sebelah kanan, bukan hanya set lain (a.union([5, 6])). Pilih mana yang lebih mudah dibaca dalam konteksnya.

2.10.6. Apa yang bisa masuk ke dalam set#

Elemen set harus hashable -- batasan yang sama dengan kunci dict. int, float, str, bool, bytes, dan tuple (ketika isinya sendiri hashable) semuanya berfungsi. list dan dict tidak; mencoba menambahkan salah satunya akan memunculkan TypeError.

2.10.7. frozenset#

Sebuah set biasa bersifat mutable: setiap panggilan ke add / remove / discard mengubah objek di tempat. Mutabilitas tersebut mendiskualifikasinya dari being hashable, sehingga set tidak dapat digunakan sebagai kunci dict atau sebagai anggota set lain.

frozenset adalah pasangan immutable-nya. Ia memiliki pencarian dan operator yang sama (in, |, &, -, ^) seperti set, tetapi tidak ada add / remove dan tidak ada metode yang melakukan mutasi. Karena tidak ada yang dapat mengubah isinya, hash dari frozenset terdefinisi dengan baik -- sehingga ia adalah hashable:

primary = frozenset({"red", "green", "blue"})
secondary = frozenset({"yellow", "purple", "orange"})

palettes = {
    primary: "RGB",
    secondary: "mixed",
}

print(palettes[primary])

Output:

RGB

Buat frozenset dari iterable apa pun -- frozenset() untuk kasus kosong, frozenset(some_set) untuk mengambil snapshot immutable dari set yang ada:

snapshot = frozenset(s)         # immutable copy of s
s.add("new")                    # snapshot does not change

Dua alasan umum untuk menggunakannya:

  • Gunakan sebagai kunci dict atau anggota set. Di mana satu nilai tidak dapat menangkap apa yang Anda butuhkan, sebuah frozenset dari nilai-nilai bisa -- "set fitur yang didukung oleh driver ini", "set pin yang digunakan profil ini".

  • Kunci sebuah konstanta. Sebuah frozenset tingkat modul dari nama-nama yang diizinkan tidak dapat secara tidak sengaja dimutasi oleh pemanggil; sebuah set biasa bisa. Lebih baik gunakan frozenset untuk apa pun yang dimaksudkan sebagai read-only setelah konstruksi.