2.10. Skupovi¶
Skup je neuređena zbirka jedinstvenih stavki. Dodavanje vrijednosti koja je već prisutna nema učinka; iteracija daje svaku vrijednost točno jednom. Skupovi su pravi alat kada su pripadnost i uklanjanje duplikata bitni, a redoslijed nije.
2.10.1. Stvaranje skupa¶
Koristite vitičaste zagrade za neprazan skup ili set() za prazan:
colours = {"red", "green", "blue"}
empty = set()
Vitičaste zagrade izgledaju poput literala dict; {} samo za sebe prazan je rječnik, a ne prazan skup – jedna od povijesnih nesreća Pythona. Za prazan slučaj koristite set().
set() također gradi skup iz bilo kojeg iterabilnog objekta, što je standardni način za uklanjanje duplikata iz niza:
nums = [1, 2, 2, 3, 1, 4]
unique = set(nums)
print(unique)
Izlaz:
{1, 2, 3, 4}
Redoslijed ispisa može varirati – skupovi ne jamče iteriranje u nekom određenom redoslijedu.
2.10.2. Skup nasuprot rječniku¶
Skupovi i rječnici oba pohranjuju jedinstvene stavke u raspršenoj tablici. Razlika je u tome što svaka stavka nosi sa sobom:
dictpohranjuje parove ključ-vrijednost. Pretraživanje ključa vraća njegovu vrijednost.setpohranjuje samo stavke. Pretraživanje stavke govori vam je li ona prisutna.
Izbor između to dvoje ovisi o tome znači li vrijednost uz svaku stavku išta:
Posegnite za skupom kada uz svaku stavku ne pripada nikakva vrijednost – zanima vas samo je li stavka prisutna, ili kombinirate skupine jedinstvenih stavki unijom / presjekom.
Posegnite za rječnikom kada je svaka stavka uparena s podatkom koji pretraživanje treba dohvatiti – konfiguracijska mapa, predmemorija, brojač s ključem po imenu.
Ta dva tipa dijele dosta površinske sintakse, odakle dolazi najveća zbrka. Razlike u jednom bloku:
set |
dict |
|
|---|---|---|
sadrži |
jedinstvene stavke |
jedinstvene ključeve, svaki s vrijednošću |
popunjen literal |
|
|
prazan literal |
|
|
provjera pripadnosti |
|
|
dohvati vrijednost |
nije primjenjivo |
|
dodaj stavku |
|
|
iteriraj |
daje stavke |
daje ključeve (koristite |
Asimetrija između popunjenog i praznog literala zamka je koju vrijedi istaknuti:
Vitičaste zagrade sa stavkama u sebi –
{1, 2, 3}– literal su skupa; vitičaste zagrade s parovima ključ-vrijednost –{"a": 1}– literal su rječnika. Parser ih razlikuje prema onome što je unutra.Vitičaste zagrade s ničim unutra –
{}– prazan su rječnik, a ne prazan skup. Rječnici su došli prvi; prazan literal pripada njima. Prazan skup uopće nema literal s vitičastim zagradama i mora se napisati kaoset().
Uobičajen obrazac kada se uvijek čitaju samo ključevi rječnika jest prijelaz na skup – on čini namjeru očiglednom i uklanja neiskorištene vrijednosti iz memorije.
2.10.3. Dodavanje i uklanjanje¶
set.add()– umeće jednu stavku.set.discard()– uklanja stavku ako je prisutna, ne čini ništa ako nije.set.remove()– uklanja stavku; izazivaKeyErrorako je nema.set.clear()– prazni skup.
s = {1, 2, 3}
s.add(4)
s.discard(99) # silent: 99 not in s
s.remove(2)
print(s)
Izlaz:
{1, 3, 4}
2.10.4. Pripadnost¶
Operator in provjerava pripadnost. Na skupu je to otprilike konstantno vrijeme bez obzira na veličinu – što je glavni razlog da odaberete skup umjesto list kada samo trebate pitati „je li ova vrijednost unutra”:
if "red" in colours:
print("colour is allowed")
list s istim sadržajem pretraživao bi se od početka svaki put, što je u redu za deset stavki, ali sporo za deset tisuća.
2.10.5. Operacije nad skupovima¶
Dva skupa mogu se kombinirati uobičajenim matematičkim operacijama. Svaka ima i oblik operatora i oblik metode:
a | bilia.union(b)– sve što je u bilo kojem od skupova.a & bilia.intersection(b)– samo ono što se pojavljuje u oba.a - bilia.difference(b)– ua, ali ne ub.a ^ bilia.symmetric_difference(b)– u jednom, ali ne u oba.
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b)
print(a & b)
print(a - b)
print(a ^ b)
Izlaz:
{1, 2, 3, 4, 5, 6}
{3, 4}
{1, 2}
{1, 2, 5, 6}
Oblici operatora samo su za čitanje; oblici metoda prihvaćaju bilo koji iterabilni objekt s desne strane, ne samo drugi skup (a.union([5, 6])). Odaberite onaj koji se bolje čita u kontekstu.
2.10.6. Što može ići u skup¶
Elementi skupa moraju biti raspršivi (hashable) – isto ograničenje kao kod ključeva dict. int, float, str, bool, bytes i tuple (kada je njezin sadržaj sam po sebi raspršiv) svi rade. list i dict ne rade; pokušaj dodavanja jednog od njih izaziva TypeError.
2.10.7. frozenset¶
Obični set je promjenjiv: svaki poziv add / remove / discard mijenja objekt na mjestu. Ta promjenjivost ga diskvalificira iz toga da bude raspršiv, pa se skup ne može koristiti kao ključ dict ni kao član drugog skupa.
frozenset nepromjenjiv je pandan. Ima iste pretrage i operatore (in, |, &, -, ^) kao set, ali nema add / remove ni metode koje ga mijenjaju. Budući da se njegov sadržaj nikad ne može promijeniti, raspršena vrijednost (hash) za frozenset dobro je definirana – pa jest raspršiv:
primary = frozenset({"red", "green", "blue"})
secondary = frozenset({"yellow", "purple", "orange"})
palettes = {
primary: "RGB",
secondary: "mixed",
}
print(palettes[primary])
Izlaz:
RGB
Frozenset se gradi iz bilo kojeg iterabilnog objekta – frozenset() za prazan slučaj, frozenset(some_set) za nepromjenjivu snimku postojećeg skupa:
snapshot = frozenset(s) # immutable copy of s
s.add("new") # snapshot does not change
Dva česta razloga da posegnete za njim:
Uporaba kao ključa rječnika ili člana skupa. Svugdje gdje jedna vrijednost ne može obuhvatiti ono što vam treba, može
frozensetvrijednosti – „skup značajki koje ovaj upravljač podržava”, „skup pinova koje ovaj profil koristi”.Zaključavanje konstante.
frozensetna razini modula s dopuštenim imenima ne može slučajno izmijeniti pozivatelj; običnisetmože. Dajte prednostfrozensetza sve što treba biti samo za čitanje nakon stvaranja.