2.10. Množiny¶
Množina je neuspořádaná kolekce jedinečných položek. Přidání hodnoty, která je již přítomna, nemá žádný efekt; iterace poskytuje každou hodnotu právě jednou. Množiny jsou tím správným nástrojem, když záleží na členství a odstranění duplicit a nezáleží na pořadí.
2.10.1. Vytvoření množiny¶
Pro neprázdnou množinu použijte složené závorky, nebo set() pro prázdnou:
colours = {"red", "green", "blue"}
empty = set()
Složené závorky vypadají jako literál dict; samotné {} je prázdný slovník, nikoli prázdná množina – jedna z historických nehod Pythonu. Pro prázdný případ použijte set().
set() také vytvoří množinu z libovolného iterovatelného objektu, což je standardní způsob odstranění duplicit z posloupnosti:
nums = [1, 2, 2, 3, 1, 4]
unique = set(nums)
print(unique)
Výstup:
{1, 2, 3, 4}
Pořadí výpisu se může lišit – množiny neslibují iteraci v žádném konkrétním pořadí.
2.10.2. Množina vs slovník¶
Množiny i slovníky ukládají jedinečné položky v hashovací tabulce. Rozdíl je v tom, co každá položka nese s sebou:
dictukládá dvojice klíč-hodnota. Vyhledání klíče vrátí jeho hodnotu.setukládá pouze položky. Vyhledání položky vám řekne, zda tam je.
Volba mezi těmito dvěma je o tom, zda hodnota vedle každé položky něco znamená:
Sáhněte po množině, když k položce nepatří žádná hodnota – záleží vám pouze na tom, zda je položka přítomna, nebo kombinujete skupiny jedinečných položek pomocí sjednocení / průniku.
Sáhněte po slovníku, když je každá položka spárována s daty, která má vyhledání získat – konfigurační mapa, mezipaměť, čítač indexovaný jménem.
Tyto dva typy sdílejí hodně povrchové syntaxe, odkud pochází většina zmatku. Rozdíly v jednom bloku:
množina |
slovník |
|
|---|---|---|
obsahuje |
jedinečné položky |
jedinečné klíče, každý s hodnotou |
naplněný literál |
|
|
prázdný literál |
|
|
test členství |
|
|
získání hodnoty |
nelze |
|
přidání položky |
|
|
iterace |
poskytuje položky |
poskytuje klíče (pro dvojice použijte |
Asymetrie mezi naplněnými a prázdnými literály je záludnost, kterou stojí za to zdůraznit:
Složené závorky s položkami uvnitř –
{1, 2, 3}– jsou literál množiny; složené závorky s dvojicemi klíč-hodnota –{"a": 1}– jsou literál slovníku. Parser je rozliší podle toho, co je uvnitř.Složené závorky s ničím uvnitř –
{}– jsou prázdný slovník, nikoli prázdná množina. Slovníky byly první; prázdný literál patří jim. Prázdná množina nemá žádný literál se závorkami a musí se zapsat jakoset().
Běžným vzorem, když se ze slovníku kdy čtou pouze klíče, je přejít na množinu – to činí záměr zřejmým a odstraňuje nevyužité hodnoty z paměti.
2.10.3. Přidávání a odebírání¶
set.add()– vloží jednu položku.set.discard()– odebere položku, pokud je přítomna, a neudělá nic, pokud není.set.remove()– odebere položku; vyvoláKeyError, pokud chybí.set.clear()– vyprázdní množinu.
s = {1, 2, 3}
s.add(4)
s.discard(99) # silent: 99 not in s
s.remove(2)
print(s)
Výstup:
{1, 3, 4}
2.10.4. Členství¶
Operátor in testuje členství. U množiny je to zhruba konstantní čas bez ohledu na velikost – což je hlavní důvod, proč zvolit množinu před list, když potřebujete pouze zjistit „je tato hodnota tam“:
if "red" in colours:
print("colour is allowed")
list se stejným obsahem by procházel od začátku pokaždé, což je v pořádku pro deset položek, ale pomalé pro deset tisíc.
2.10.5. Operace s množinami¶
Dvě množiny lze kombinovat pomocí obvyklých matematických operací. Každá má jak operátorovou, tak metodovou formu:
a | bneboa.union(b)– vše v kterékoli množině.a & bneboa.intersection(b)– pouze to, co se vyskytuje v obou.a - bneboa.difference(b)– va, ale ne vb.a ^ bneboa.symmetric_difference(b)– v jedné, ale ne v obou.
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b)
print(a & b)
print(a - b)
print(a ^ b)
Výstup:
{1, 2, 3, 4, 5, 6}
{3, 4}
{1, 2}
{1, 2, 5, 6}
Operátorové formy jsou jen pro čtení; metodové formy přijímají na pravé straně libovolný iterovatelný objekt, nejen jinou množinu (a.union([5, 6])). Vyberte si tu, která se v daném kontextu lépe čte.
2.10.6. Co může jít do množiny¶
Prvky množiny musí být hashovatelné – stejné omezení jako u klíčů dict. int, float, str, bool, bytes a tuple (pokud je jeho obsah sám hashovatelný) všechny fungují. list a dict nikoli; pokus o přidání některého z nich vyvolá TypeError.
2.10.7. frozenset¶
Běžná set je měnitelná: každé volání add / remove / discard mění objekt na místě. Tato měnitelnost ji diskvalifikuje z hashovatelnosti, takže množina nemůže být použita jako klíč dict ani jako člen jiné množiny.
frozenset je neměnný protějšek. Má stejná vyhledávání a operátory (in, |, &, -, ^) jako set, ale žádné add / remove a žádné metody, které mutují. Protože jeho obsah se nikdy nemůže změnit, je hash frozenset dobře definovaný – takže je hashovatelný:
primary = frozenset({"red", "green", "blue"})
secondary = frozenset({"yellow", "purple", "orange"})
palettes = {
primary: "RGB",
secondary: "mixed",
}
print(palettes[primary])
Výstup:
RGB
Vytvořte frozenset z libovolného iterovatelného objektu – frozenset() pro prázdný případ, frozenset(some_set) pro pořízení neměnného snímku existující množiny:
snapshot = frozenset(s) # immutable copy of s
s.add("new") # snapshot does not change
Dva běžné důvody, proč po něm sáhnout:
Použití jako klíč slovníku nebo člen množiny. Všude, kde jediná hodnota nedokáže zachytit to, co potřebujete, dokáže to
frozensethodnot – „množina funkcí podporovaných tímto ovladačem“, „množina pinů, které tento profil používá“.Uzamčení konstanty. Konstantu
frozensetpovolených jmen na úrovni modulu nemůže volající nechtěně zmutovat; běžnousetano. Pro cokoli, co má být po vytvoření jen pro čtení, dejte přednostfrozenset.