Kompletny przewodnik z przykładami kodu

W tym przewodniku zapoznasz się z fundamentalnymi aspektami zbiorów w Pythonie oraz z różnymi metodami, które pozwalają na ich modyfikację.

Zbiory stanowią jedną z wbudowanych struktur danych w Pythonie. Są idealne, gdy potrzebujesz pracować z kolekcją unikalnych elementów.

W kolejnych sekcjach omówimy podstawowe zasady działania zbiorów Pythona oraz metody, które umożliwią efektywną pracę z nimi. Następnie przejdziemy do typowych operacji na zbiorach, które można wykonywać w Pythonie.

Zacznijmy!

Podstawowe informacje o zbiorach w Pythonie

W Pythonie zbiór to nieuporządkowana kolekcja, w której każdy element jest unikalny. Innymi słowy, w zbiorze nie mogą występować duplikaty.

Zbiory są strukturami zmiennymi, co oznacza, że można dodawać do nich elementy i je z nich usuwać. Mogą przechowywać elementy różnych typów danych. Istotne jest jednak, aby każdy element w zbiorze był haszowalny.

Obiekt w Pythonie uznaje się za haszowalny, jeśli jego wartość hash nie ulega zmianie w czasie. Większość obiektów niezmiennych, takich jak ciągi znaków, krotki i słowniki, jest haszowalna.

Szczegółowo omówimy proces tworzenia zbiorów. Na razie spójrzmy na poniższe dwa przykłady:

py_set = {0,1,2,(2,3,4),'Cool!'}
py_set = {0,1,2,[2,3,4],'Oops!'}

# Output
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-40-2d3716c7fe01> in <module>()
----> 1 py_set = {0,1,2,[2,3,4],'Oops!'}

TypeError: unhashable type: 'list'

Pierwszy zbiór składa się z trzech liczb, krotki i ciągu znaków. Inicjalizacja tego zbioru przebiega bezproblemowo. Natomiast drugi zbiór zawiera listę zamiast krotki. Lista jest kolekcją zmienną, a więc nie można jej haszować, co powoduje błąd TypeError podczas inicjalizacji.

📑 Podsumowując, zbiór Pythona można zdefiniować jako zmienną kolekcję unikalnych i haszowalnych elementów.

Jak utworzyć zbiór w Pythonie?

Zaczniemy od poznania różnych sposobów tworzenia zbiorów w Pythonie.

#1. Użycie jawnej inicjalizacji

Zbiór w Pythonie można utworzyć, definiując jego elementy, oddzielone przecinkami i umieszczone w nawiasach klamrowych {}.

py_set1 = {'Python','C','C++','JavaScript'}
type(py_set1)

# Output
set

Osoby zaznajomione z listami w Pythonie wiedzą, że [] inicjuje pustą listę. Mimo że zbiory są umieszczane w nawiasach klamrowych {}, nie można ich zainicjować za pomocą pustych nawiasów {}. Dzieje się tak, ponieważ {} inicjuje słownik, a nie zbiór.

py_set2 = {}
type(py_set2)

# Output
dict

Możesz użyć funkcji type(), aby upewnić się, że `py_set2` jest słownikiem (dict).

#2. Użycie funkcji set()

Jeśli chcesz utworzyć pusty zbiór, a później dodać do niego elementy, możesz użyć funkcji `set()`.

py_set3 = set()
type(py_set3)

# Output
set

#3. Konwersja innych struktur iterowalnych do zbioru

Inną metodą tworzenia zbiorów jest przekształcenie innych struktur iterowalnych, takich jak listy i krotki, w zbiory za pomocą funkcji `set(iterable)`.

py_list = ['Python','C','C++','JavaScript','C']
py_set4 = set(py_list)
print(py_set4)
# {'C++', 'C', 'JavaScript', 'Python'} # repeating element 'C' removed
type(py_set4)
# set

W powyższym przykładzie 'C’ pojawia się dwa razy w `py_list`. Natomiast w zbiorze `py_set4` 'C’ występuje tylko raz, ponieważ zbiór zawiera wyłącznie unikalne elementy. Metoda konwersji do zbioru jest często wykorzystywana do usuwania duplikatów z list w Pythonie.

Jak dodawać elementy do zbioru w Pythonie?

Zacznijmy od utworzenia pustego zbioru o nazwie `py_set` i będziemy go używać w dalszej części tego przewodnika.

py_set = set()
len(py_set) # returns the length of a set
# Output
0

#1. Użycie metody .add()

Aby dodać elementy do zbioru, możesz skorzystać z metody `.add()`. Składnia `set.add(element)` dodaje `element` do zbioru.

Dla przejrzystości, dodamy elementy do zbioru i będziemy go wyświetlać po każdym kroku.

▶️ Dodajmy ciąg znaków 'Python’ jako element do `py_set`.

py_set.add('Python')
print(py_set)

# Output
{'Python'}

Następnie dodajmy kolejny element.

py_set.add('C++')
print(py_set)

# Output
{'Python', 'C++'}

Należy pamiętać, że metoda `.add()` dodaje element do zbioru tylko wtedy, gdy nie występuje w nim. Jeżeli element, który próbujesz dodać, już znajduje się w zbiorze, operacja dodawania nie będzie miała żadnego efektu.

Aby to sprawdzić, spróbujmy dodać 'C++’ do `py_set`.

py_set.add('C++')
print(py_set)

# Output
{'Python', 'C++'}

Zbiór zawiera już 'C++’, więc operacja dodawania jest ignorowana.

▶️ Dodajmy do zbioru kilka kolejnych elementów.

py_set.add('C')
print(py_set)
py_set.add('JavaScript')
print(py_set)
py_set.add('Rust')
print(py_set)

# Output
{'Python', 'C++', 'C'}
{'JavaScript', 'Python', 'C++', 'C'}
{'Rust', 'JavaScript', 'Python', 'C++', 'C'}

#2. Użycie metody .update()

Do tej pory poznaliśmy metodę dodawania pojedynczych elementów do zbioru.

Co zrobić, jeśli chcesz dodać do zbioru sekwencję elementów?

Możesz użyć metody `.update()` o składni: `set.update(kolekcja)`, aby dodać elementy z kolekcji do zbioru. Kolekcją może być lista, krotka, słownik itd.

py_set.update(['Julia','Ruby','Scala','Java'])
print(py_set)

# Output
{'C', 'C++', 'Java', 'JavaScript', 'Julia', 'Python', 'Ruby', 'Rust', 'Scala'}

Metoda ta jest przydatna, gdy chcesz dodać kolekcję elementów do zbioru bez tworzenia nowego obiektu w pamięci.

W kolejnej sekcji nauczymy się, jak usuwać elementy ze zbioru.

Jak usuwać elementy ze zbioru w Pythonie?

Rozważmy zbiór `py_set` w stanie sprzed operacji aktualizacji.

py_set = {'C++', 'JavaScript', 'Python', 'Rust', 'C'}

#1. Użycie metody .pop()

`set.pop()` losowo usuwa element ze zbioru i zwraca go. Wywołajmy metodę `pop` na `py_set` i zobaczmy, co zostanie zwrócone.

py_set.pop()

# Output
'Rust'

Tym razem wywołanie metody `.pop()` zwróciło 'Rust’.

Uwaga: ponieważ metoda `.pop()` zwraca element losowy, wynik może być inny przy ponownym uruchomieniu kodu.

Sprawdzając zawartość zbioru, można zauważyć, że 'Rust’ już w nim nie występuje.

print(py_set)

# Output
{'JavaScript', 'Python', 'C++', 'C'}

#2. Użycie metod .remove() i .discard()

Często zachodzi potrzeba usunięcia konkretnego elementu ze zbioru. W tym celu możesz wykorzystać metody `.remove()` i `.discard()`.

`set.remove(element)` usuwa `element` ze zbioru.

py_set.remove('C')
print(py_set)

# Output
{'JavaScript', 'Python', 'C++'}

Próba usunięcia elementu, który nie występuje w zbiorze, spowoduje błąd `KeyError`.

py_set.remove('Scala')

# Output
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-58-a1abab3a8892> in <module>()
----> 1 py_set.remove('Scala')

KeyError: 'Scala'

Sprawdźmy jeszcze raz, co zawiera `py_set`. Aktualnie mamy w nim trzy elementy.

print(py_set)

# Output
{'JavaScript', 'Python', 'C++'}

Metoda `.discard(element)` również usuwa elementy ze zbioru.

py_set.discard('C++')
print(py_set)

# Output
{'JavaScript', 'Python'}

Różnica między metodami `.remove()` i `.discard()` polega na tym, że `.discard()` nie zgłasza błędu `KeyError` w przypadku próby usunięcia elementu, który nie znajduje się w zbiorze.

Jeśli spróbujemy usunąć 'Scala’ (która nie występuje) za pomocą metody `.discard()`, błąd nie zostanie zgłoszony.

py_set.discard('Scala') #no error!
print(py_set)

# Output
{'JavaScript', 'Python'}

Jak uzyskać dostęp do elementów zbioru w Pythonie?

Dotychczas nauczyliśmy się, jak dodawać i usuwać elementy ze zbiorów. Jednak nie wiemy jeszcze, jak uzyskać dostęp do poszczególnych elementów w zbiorze.

Ponieważ zbiór jest strukturą nieuporządkowaną, nie można do niej odwoływać się za pomocą indeksów. Próba dostępu do elementów zbioru za pomocą indeksu spowoduje błąd, jak pokazano poniżej.

py_set = {'C++', 'JavaScript', 'Python', 'Rust', 'C'}

print(py_set[0])

# Output
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-27-0329274f4580> in <module>()
----> 1 print(py_set[0])

TypeError: 'set' object is not subscriptable

Jak więc uzyskać dostęp do elementów w zbiorze?

Można to zrobić na dwa sposoby:

  • Iteracja po zbiorze i dostęp do każdego elementu
  • Sprawdzenie, czy element należy do zbioru

▶️ Iteracja po zbiorze i dostęp do elementów za pomocą pętli `for`.

for elt in py_set:
  print(elt)

# Output
C++
JavaScript
Python
Rust
C

Często chcemy sprawdzić, czy dany element występuje w zbiorze, za pomocą operatora `in`.

Uwaga: operator `in` zwraca `True`, jeżeli element znajduje się w zbiorze, a `False` w przeciwnym wypadku.

W tym przykładzie `py_set` zawiera 'C++’ i nie zawiera 'Julia’, więc operator `in` zwróci odpowiednio `True` i `False`.

'C++' in py_set
# True
'Julia' in py_set
# False

Jak sprawdzić rozmiar zbioru w Pythonie?

Jak już wcześniej pokazano, funkcja `len()` pozwala uzyskać liczbę elementów w zbiorze.

py_set = {'C++', 'JavaScript', 'Python', 'Rust', 'C'}
len(py_set)

# Output: 5

Jak wyczyścić zbiór w Pythonie?

Aby wyczyścić zbiór, usuwając z niego wszystkie elementy, możesz użyć metody `.clear()`.

Wywołajmy metodę `.clear()` na `py_set`.

py_set.clear()

Jeśli spróbujesz wyświetlić zbiór, otrzymasz `set()`, co oznacza, że zbiór jest pusty. Możesz również użyć funkcji `len()`, aby sprawdzić, czy jego długość wynosi zero.

print(py_set)
# set()
print(len(py_set))
# 0

Dotychczas omówiliśmy podstawowe operacje CRUD na zbiorach Pythona:

  • Tworzenie: przy użyciu funkcji `set()`, konwersji typu i inicjalizacji.
  • Odczyt: dostęp do elementów zbioru za pomocą pętli oraz operatora `in` do sprawdzania obecności elementów.
  • Aktualizacja: dodawanie, usuwanie elementów ze zbiorów i aktualizacja zbiorów.
  • Usuwanie: wyczyszczenie zbioru poprzez usunięcie wszystkich elementów.

Typowe operacje na zbiorach, wyjaśnione na przykładzie kodu Pythona

Zbiory w Pythonie umożliwiają również wykonywanie podstawowych operacji, które są znane z teorii mnogości. Omówimy je w tej sekcji.

#1. Suma zbiorów w Pythonie

W teorii mnogości suma dwóch zbiorów to zbiór, który zawiera wszystkie elementy z obu zbiorów. Jeśli mamy dwa zbiory A i B, suma zawiera elementy, które występują tylko w A, tylko w B, oraz elementy, które występują zarówno w A, jak i w B.

Aby znaleźć sumę zbiorów, można użyć operatora `|` lub metody `.union()` o składni: `setA.union(setB)`.

setA = {1,3,5,7,9}
setB = {2,4,6,8,9}

print(setA | setB)
# Output
{1, 2, 3, 4, 5, 6, 7, 8, 9}

setA.union(setB)

# Output
{1, 2, 3, 4, 5, 6, 7, 8, 9}

Suma zbiorów jest operacją przemienną, więc AUB jest tym samym co BUA. Sprawdźmy to, zamieniając miejscami `setA` i `setB` w wywołaniu metody `.union()`.

setB.union(setA)

# Output
{1, 2, 3, 4, 5, 6, 7, 8, 9}

#2. Iloczyn zbiorów w Pythonie

Inną częstą operacją na zbiorach jest iloczyn dwóch zbiorów A i B. Iloczyn zbiorów zwraca zbiór zawierający wszystkie elementy, które występują zarówno w A, jak i w B.

Aby obliczyć iloczyn, możesz użyć operatora `&` lub metody `.intersection()`, jak wyjaśniono w poniższym przykładzie.

print(setA & setB)

# Output
{9}

setA.intersection(setB)

# Output
{9}

W tym przykładzie element 9 jest obecny zarówno w `setA`, jak i w `setB`. Zatem iloczyn zbiorów zawiera tylko ten element.

Podobnie jak suma zbiorów, iloczyn zbiorów jest operacją przemienną.

setB.intersection(setA)

# Output
{9}

#3. Różnica zbiorów w Pythonie

Mając dwa zbiory, suma i iloczyn pomagają nam znaleźć elementy występujące w obu lub co najmniej jednym ze zbiorów. Z kolei różnica zbiorów pozwala na znalezienie elementów, które występują w jednym zbiorze, ale nie występują w drugim.

– `setA.difference(setB)` zwraca zbiór elementów, które występują tylko w `setA`, a nie w `setB`.

– `setB.difference(setA)` zwraca zbiór elementów, które występują tylko w `setB`, a nie w `setA`.

print(setA - setB)

print(setB - setA)

# Output
{1, 3, 5, 7}
{8, 2, 4, 6}

Oczywiście AB nie jest tym samym co BA, więc różnica zbiorów nie jest operacją przemienną.

setA.difference(setB)
# {1, 3, 5, 7}

setB.difference(setA)
# {2, 4, 6, 8}

#4. Różnica symetryczna zbiorów w Pythonie

Podczas gdy iloczyn zbiorów zwraca elementy występujące w obu zbiorach, różnica symetryczna zbiorów zwraca zbiór elementów, które występują tylko w jednym z dwóch zbiorów.

Rozważmy poniższy przykład.

setA = {1,3,5,7,10,12}
setB = {2,4,6,8,10,12}

Aby obliczyć różnicę symetryczną, możesz użyć operatora `^` lub metody `.symmetric_difference()`.

print(setA ^ setB)

# Output
{1, 2, 3, 4, 5, 6, 7, 8}

Elementy 10 i 12 występują zarówno w `setA`, jak i w `setB`, więc nie są zawarte w różnicy symetrycznej.

setA.symmetric_difference(setB)

# Output
{1, 2, 3, 4, 5, 6, 7, 8}

Ponieważ operacja różnicy symetrycznej zbiera wszystkie elementy, które występują dokładnie w jednym z dwóch zbiorów, wynikowy zbiór jest taki sam niezależnie od kolejności zbiorów. Dlatego różnica symetryczna zbiorów jest operacją przemienną.

setB.symmetric_difference(setA)

# Output
{1, 2, 3, 4, 5, 6, 7, 8}

#5. Podzbiory i nadzbiory w Pythonie

W teorii mnogości podzbiory i nadzbiory pomagają określić relację między dwoma zbiorami.

Mając dwa zbiory A i B, zbiór B jest podzbiorem zbioru A, jeśli wszystkie elementy zbioru B występują również w zbiorze A. Zbiór A jest wtedy nadzbiorem zbioru B.

Rozważmy przykład dwóch zbiorów: `languages` i `languages_extended`.

languages = {'Python', 'JavaScript','C','C++'}
languages_extended = {'Python', 'JavaScript','C','C++','Rust','Go','Scala'}

W Pythonie możesz użyć metody `.issubset()`, aby sprawdzić, czy dany zbiór jest podzbiorem innego zbioru.

`setA.issubset(setB)` zwraca `True`, jeśli `setA` jest podzbiorem `setB`; w przeciwnym razie zwraca `False`.

W tym przykładzie `languages` jest podzbiorem `languages_extended`.

languages.issubset(languages_extended)
# Output
True

Podobnie, możesz użyć metody `.issuperset()`, aby sprawdzić, czy dany zbiór jest nadzbiorem innego zbioru.

`setA.issuperset(setB)` zwraca `True`, jeśli `setA` jest nadzbiorem `setB`; w przeciwnym razie zwraca `False`.

languages_extended.issuperset(languages)
# Output
True

Ponieważ `languages_extended` jest nadzbiorem `languages`, `languages_extended.issuperset(languages)` zwraca `True`, jak pokazano powyżej.

Podsumowanie

Mam nadzieję, że ten przewodnik pomógł ci zrozumieć działanie zbiorów w Pythonie, metody zbiorów służące do operacji CRUD i typowe operacje na zbiorach. Kolejnym krokiem może być próba ich użycia w projektach w Pythonie.

Zachęcam do zapoznania się z innymi naszymi przewodnikami po Pythonie. Powodzenia w nauce!


newsblog.pl