Współbieżność, wielowątkowość, wyrażenia regularne i generatory w Pythonie

Opublikowane przez Mateusz Kędziora w dniu

img LgWlXjgl6KxmAZyVIpCg1e2j

Witajcie w kolejnym wpisie poświęconym zaawansowanym tematom w Pythonie! W dzisiejszym artykule skupimy się na czterech różnych zagadnieniach: współbieżności, wielowątkowości, wyrażeniach regularnych i generatorach.

Zacznijmy od współbieżności. Współbieżność to mechanizm pozwalający na uruchamianie kilku zadań jednocześnie, dzięki czemu możemy efektywniej wykorzystać moc obliczeniową naszego komputera. W Pythonie mamy do dyspozycji kilka różnych sposobów na realizację współbieżności, takich jak:

  • Threading: moduł threading pozwala na tworzenie wątków, czyli niezależnych od siebie sekwencji kodu, które mogą być uruchamiane jednocześnie.
  • asyncio: moduł asyncio to biblioteka do tworzenia asynchronicznych aplikacji sieciowych. Dzięki niemu możemy łatwo realizować współbieżność za pomocą tzw. „coroutines”.
  • multiprocessing: moduł multiprocessing pozwala na tworzenie procesów, czyli niezależnych od siebie instancji interpretera Python, które mogą być uruchamiane jednocześnie.

Kolejnym zagadnieniem, które chcemy omówić, jest wielowątkowość. Wielowątkowość to mechanizm pozwalający na uruchamianie kilku wątków jednocześnie. W Pythonie mamy do dyspozycji moduł threading, który umożliwia tworzenie i uruchamianie wątków. Warto jednak pamiętać, że wątki w Pythonie nie są tak „lekkie” jak w innych językach, dlatego nie zawsze jest to najlepsze rozwiązanie.

Przejdźmy do kolejnego zagadnienia, jakim są wyrażenia regularne. Wyrażenia regularne to specjalny rodzaj ciągów znaków, które służą do wyszukiwania i zamiany tekstu zgodnie z określonym wzorem. Są one bardzo przydatne do różnego rodzaju zadań związanych z przetwarzaniem tekstu, takich jak:

  • wyszukiwanie określonych fraz w tekście
  • sprawdzanie poprawności adresów email lub numerów telefonów
  • podmiana poszczególnych fragmentów tekstu

W Pythonie mamy do dyspozycji moduł re, który umożliwia korzystanie z wyrażeń regularnych. Aby skorzystać z tego modułu, musimy najpierw zaimportować go do swojego kodu:

import re

Następnie możemy już korzystać z różnych funkcji i metod dostępnych w module re, takich jak np. re.search(), re.sub() czy re.findall().

Ostatnim zagadnieniem, które chcemy omówić, są generatory i dekoratory. Generatory to specjalne funkcje, które zwracają iterator pozwalający na przechodzenie przez kolejne elementy sekwencji. Generatory pozwalają na duże oszczędności pamięci, ponieważ nie tworzą całej sekwencji naraz, a jedynie zwracają pojedyncze elementy w momencie ich potrzebowania.

Aby stworzyć generator, wystarczy zamiast słowa kluczowego „return” użyć słowa „yield”. Przykład:

def generator():
    yield 1
    yield 2
    yield 3

Dekoratory to specjalne funkcje, które pozwalają na modyfikowanie innych funkcji bez konieczności ich bezpośredniej edycji. Są one bardzo przydatne w przypadku, gdy chcemy dodać jakiś dodatkowy element funkcjonalności.

Kontynuując nasz wpis o zaawansowanych tematach w Pythonie, skupmy się teraz na dekoratorach. Aby stworzyć dekorator, musimy najpierw zdefiniować funkcję, która będzie służyć jako opakowanie dla naszej głównej funkcji. Następnie, wewnątrz tej funkcji, deklarujemy naszą główną funkcję i dodajemy do niej dowolne dodatkowe funkcjonalności. Przykład:

def dekorator(func):
    def opakowanie():
        print("Przed wywołaniem funkcji")
        func()
        print("Po wywołaniu funkcji")
    return opakowanie

def powiedz_cześć():
    print("Cześć!")

powiedz_cześć = dekorator(powiedz_cześć)

W powyższym przykładzie stworzyliśmy dekorator „dekorator”, który dodaje do funkcji „powiedz_cześć” dodatkowe komunikaty przed i po jej wywołaniu.

Istnieje także skrócona składnia do tworzenia dekoratorów, za pomocą słowa kluczowego „def” oraz symbolu „@”. Przykład:

@dekorator
def powiedz_cześć():
    print("Cześć!")

Istotnym aspektem pracy z współbieżnością i wielowątkowością jest synchronizacja dostępu do zasobów współdzielonych przez wiele wątków. W Pythonie mamy do dyspozycji kilka sposobów na zapewnienie takiej synchronizacji:

  • Blokady (ang. locks): moduł threading zawiera klasę Lock, która pozwala na blokowanie dostępu do pewnych fragmentów kodu tylko dla jednego wątku naraz.
  • Semafory (ang. semaphores): moduł threading zawiera także klasę Semaphore, która pozwala na ograniczenie liczby wątków mogących jednocześnie wykonywać pewien fragment kodu.
  • Warunki (ang. conditions): moduł threading zawiera również klasę Condition, która pozwala na „wstrzymywanie” wątków do momentu, aż nie zostaną spełnione określone warunki.
  • Zmienne wyścigu (ang. race conditions): są to sytuacje, w których wiele wątków jednocześnie próbuje zmodyfikować pewną zmienną współdzieloną, co może prowadzić do nieoczekiwanych rezultatów. Aby uniknąć zmiennych wyścigu, należy odpowiednio zsynchronizować dostęp do takich zmiennych.

Pamiętajcie, że praca z współbieżnością i wielowątkowością może być trudna i łatwo o błędy. Dlatego ważne jest, aby dokładnie przemyśleć konstrukcję swojego kodu oraz odpowiednio zsynchronizować dostęp do współdzielonych zasobów.

To już koniec naszego wpisu o zaawansowanych tematach w Pythonie. Mamy nadzieję, że dzięki niemu lepiej zrozumieliście zagadnienia związane z współbieżnością, wielowątkowością, wyrażeniami regularnymi i generatorami oraz dekoratorami.

Tekst wygenerowany przy pomocy chat.openai.com.

Kategorie: Python

Mateusz Kędziora

Jestem uczniem technikum a prowadzeniem bloga zajmuje się hobbystycznie.

Dodaj komentarz

Avatar placeholder

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *