Masz wrażenie, że nikt nie czyta Twojego CV? Nie dostajesz zaproszeń na rozmowy rekrutacyjne?
Sprawdź swoje umiejętności techniczne a MockIT pomoże Ci znaleźć pracę w IT!
Python: Wiedza w pigułce, którą każdy powinien mieć
Nie wiesz od czego zacząć naukę Pythona? A może chciałbyś się dowiedzieć czy opanowałeś absolutne podstawy tego języka? W tym artykule przybliżę Ci fundamenty wiedzy z Pythona.
Intro
Python to jeden z najpopularniejszych i najbardziej wszechstronnych języków programowania na świecie. Jego czytelna składnia i bogaty wybór bibliotek sprawiają, że jest to doskonały wybór zarówno dla początkujących programistów, jak i doświadczonych developerów.
W tym artykule przedstawię kluczowe koncepcje i funkcjonalności języka Python oraz postaram się przypomnieć jego podstawy. Zanim przejdziemy do bibliotek i frameworków chciałbym zacząć od ogólnych zasad pisania kodu.
Clean Code: SOLID, KISS, DRY
Podczas pisania kodu w Pythonie (a także w innych językach programowania), istnieje szereg zasad, których przestrzeganie pomaga utrzymać kod czytelnym, elastycznym i łatwym do zarządzania. Wśród tych zasad wyróżniamy SOLID, KISS i DRY, które są fundamentalne dla tworzenia wysokiej jakości kodu.
SOLID
SOLID to mnemonik określający pięć podstawowych zasad projektowania obiektowego:
S - Single Responsibility Principle (Zasada pojedynczej odpowiedzialności): Klasa powinna mieć tylko jedną odpowiedzialność, czyli być odpowiedzialna za jedną konkretną funkcjonalność. Dzięki temu unikamy zbyt dużych i złożonych klas, co ułatwia zarządzanie kodem.
O - Open/Closed Principle (Zasada otwarte/zamknięte): Klasa powinna być otwarta na rozszerzenie, ale zamknięta na modyfikację. Zmiany w klasie powinny być dokonywane poprzez dodawanie nowego kodu, a nie zmienianie istniejącego.
L - Liskov Substitution Principle (Zasada podstawienia Liskov): Obiekty danej klasy powinny być zastępowalne przez obiekty ich podklas bez zmiany działania programu. Dzięki temu zachowujemy spójność i elastyczność kodu.
I - Interface Segregation Principle (Zasada segregacji interfejsów): Interfejsy powinny być konkretne dla danego klienta, unikamy tworzenia ogólnych interfejsów, które wymagają od klientów implementowania niepotrzebnych funkcji.
D - Dependency Inversion Principle (Zasada odwrócenia zależności): Moduły powinny być zależne od abstrakcji, a nie od konkretnych implementacji. Dzięki temu zmniejszamy zależności między modułami i ułatwiamy testowanie oraz rozwijanie kodu.
KISS
KISS, czyli Keep It Simple, Stupid, to zasada zachęcająca do pisania prostego, zrozumiałego kodu. Unikanie nadmiernego skomplikowania jest kluczowe dla utrzymania czytelności i łatwości utrzymania kodu. Im bardziej skomplikowany kod, tym trudniejsze jest jego zrozumienie i modyfikacja w przyszłości. Stosowanie prostych rozwiązań, klarownych nazw zmiennych i funkcji oraz unikanie nadmiernego zagnieżdżania warunków i pętli są kluczowymi praktykami zgodnymi z zasadą KISS.
DRY
DRY, czyli Don’t Repeat Yourself, to zasada mówiąca o unikaniu powtarzania się kodu. Wszelkie powtarzające się fragmenty kodu powinny być zrefaktoryzowane do oddzielnych funkcji lub klas, co pozwala na łatwiejsze zarządzanie i utrzymanie kodu. Powtarzający się kod jest trudny w utrzymaniu, ponieważ wymaga zmian w wielu miejscach w przypadku konieczności modyfikacji. Dzięki zastosowaniu zasady DRY, kod staje się bardziej modułowy i elastyczny.
Składnia i podstawowe typy danych w Pythonie
Python wyróżnia się czytelną i intuicyjną składnią, co czyni go bardzo przyjaznym dla użytkownika. Jego dynamiczna natura pozwala na elastyczne operowanie na różnych typach danych, bez konieczności wcześniejszego deklarowania typu zmiennej.
Typy danych w Pythonie
Integers (liczby całkowite): Są to liczby całkowite, takie jak 1, 100, -5 itp. Python pozwala na wykonywanie podstawowych operacji arytmetycznych na liczbach całkowitych, takich jak dodawanie +, odejmowanie -, mnożenie *, dzielenie /, dzielenie całkowite // oraz operacje modulo %.
Floats (liczby zmiennoprzecinkowe): Obejmują liczby zmiennoprzecinkowe, np. 3.14, 2.5, -0.5 itp. Są używane do reprezentowania liczb dziesiętnych. Python obsługuje operacje matematyczne na liczbach zmiennoprzecinkowych takie jak dodawanie, odejmowanie, mnożenie i dzielenie.
Strings (łańcuchy znaków): Są to sekwencje znaków umieszczone w cudzysłowiu, np. “Hello, World!”. W Pythonie łańcuchy znaków są niezmiennymi obiektami, co oznacza, że po utworzeniu nie można ich modyfikować. Python oferuje wiele operacji na łańcuchach, takich jak konkatenacja +, indeksowanie [], wycinanie [start:stop:step] oraz wiele metod do manipulacji tekstem.
Lists (listy): Listy są kolekcjami elementów, które mogą być różnych typów. Tworzymy je za pomocą nawiasów kwadratowych [], np. [1, 2, 3]. Listy w Pythonie są mutowalne, co oznacza, że można dodawać, usuwać i modyfikować ich elementy.
Tuples (krotki): Krotki są podobne do list, ale są niezmiennymi kolekcjami elementów. Tworzymy je za pomocą nawiasów okrągłych (), np. (1, 2, 3). Krotki są bardziej wydajne od list, gdyż zajmują mniej miejsca w pamięci, ale nie można ich modyfikować po utworzeniu.
Dictionaries (słowniki): Słowniki to kolekcje par klucz-wartość, gdzie każdy klucz jest unikalny. Tworzymy je za pomocą nawiasów klamrowych {}, np. {“klucz”: “wartość”, “imie”: “Anna”}. Słowniki umożliwiają szybkie dostęp do wartości poprzez klucz i są używane do przechowywania danych w formie par.
Instrukcje sterujące, pętle oraz typowanie w Pythonie
Python oferuje wiele instrukcji sterujących do kontroli przepływu programu oraz pętle do powtarzania kodu. Te elementy są kluczowe dla budowania elastycznych i dynamicznych programów. Oto kilka przykładów:
Instrukcje sterujące if, elif, else służą do wykonania różnych bloków kodu w zależności od spełnienia warunków.
age = 25
if age < 18:
print("You are underage")
elif age >= 18 and age < 65:
print("You are an adult")
else:
print("You are senior")
Pętla while wykonuje blok kodu, dopóki warunek jest spełniony.
x = 0
while x < 5:
print(x)
x += 1
Pętla for służy do iteracji po sekwencjach, takich jak listy, krotki, słowniki itp.
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
print(fruit)
Funkcja range() generuje sekwencję liczb, które można wykorzystać w pętlach.
for i in range(5):
print(i)
Funkcja enumerate() służy do iteracji po sekwencji jednocześnie zwracając indeksy i elementy.
colors = ["red", "green", "blue"]
for index, color in enumerate(colors):
print(f"Color {index}: {color}")
Instrukcje break i continue pozwalają kontrolować działanie pętli. Break przerywa pętlę, a continue przechodzi do następnej iteracji.
for i in range(10):
if i == 5:
break # break loop when value of "i" reaches 5
if i % 2 == 0:
continue # skip iteration if value of "i" is even
print(i)
Python jest językiem dynamicznie typowanym, co oznacza, że nie musimy deklarować typu zmiennej podczas jej tworzenia. Jednak od wersji Pythona 3.6 wprowadzono możliwość dodawania adnotacji typów, co pozwala na pewne wskazanie typu danej zmiennej. W dzisiejszych czasach, często korzysta się z typów w Pythonie. Poprawia to czytelność kodu i nieco ogranicza podatność na błędy.
Przykłady:
name: str = "Alice"
age: int = 30
is_adult: bool = True
def greet(name: str) -> str:
return f"Hello, {name}!"
def void(a,b) -> None:
print(a,b)
Testy jednostkowe w Pythonie
Testy jednostkowe są kluczowym elementem procesu programowania, zwłaszcza w kontekście Test-Driven Development (TDD) i utrzymywania wysokiej jakości kodu. W Pythonie, do tworzenia testów jednostkowych, często używana jest biblioteka unittest lub narzędzie pytest. Dzięki testom jednostkowym możemy sprawdzać poprawność działania naszych funkcji, metod i klas.
Biblioteka unittest
Biblioteka unittest jest częścią biblioteki standardowej Pythona i zapewnia narzędzia do tworzenia i uruchamiania testów jednostkowych. Oto przykład prostego testu jednostkowego w unittest:
import unittest
def add(a, b):
return a + b
class TestMathOperations(unittest.TestCase):
def test_addition(self):
self.assertEqual(add(2, 3), 5)
self.assertEqual(add(-1, 1), 0)
self.assertEqual(add(0, 0), 0)
if __name__ == '__main__':
unittest.main()
Narzędzie pytest
Pytest jest bardziej nowoczesnym narzędziem do testowania w Pythonie i oferuje bardziej przejrzystą i wygodną składnię niż unittest.
def add(a, b):
return a + b
def test_addition():
assert add(2, 3) == 5
assert add(-1, 1) == 0
assert add(0, 0) == 0
W przypadku pytest nie musimy dziedziczyć z klasy czy używać specjalnych asercji, co sprawia, że pisanie testów jest bardziej przejrzyste i kompaktowe.
Wielowątkowość
Wielowątkowość w Pythonie pozwala na równoległe wykonywanie kilku części programu jednocześnie. Jest to przydatne zwłaszcza w sytuacjach, gdy chcemy wykonywać operacje równolegle, takie jak przetwarzanie danych, obsługa żądań sieciowych czy interakcje z urządzeniami wejścia-wyjścia. W Pythonie możemy korzystać z wątków za pomocą modułu threading oraz procesów za pomocą modułu multiprocessing.
import threading
import time
def worker(num):
print(f"Worker {num} started")
time.sleep(2) # Mock of certain instructions
print(f"Worker {num} finished")
# Thread creation
threads = []
for i in range(3):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()
# Waiting for threads to finish
for t in threads:
t.join()
print("All threads finished")
Warto zauważyć, że korzystając z wątków (threading) w Pythonie, nie uzyskujemy pełnej równoległości ze względu na Global Interpreter Lock (GIL), który ogranicza jednoczesne wykonywanie kodu Pythona w jednym procesie. Dlatego, jeśli zależy nam na pełnej równoległości, warto rozważyć użycie procesów (multiprocessing). Dla zainteresowanych odsyłam do innego artykułu w języku angielskim opisujący to dokładniej: link
Biblioteka Pandas
Pandas to potężna biblioteka do manipulacji i analizy danych w języku Python. Oferuje wydajne i łatwe w użyciu struktury danych, takie jak DataFrame, które umożliwiają pracę z danymi w sposób podobny do arkuszy kalkulacyjnych
Struktury danych w Pandas
DataFrame jest główną strukturą danych w Pandas, przypominającą tabelę bazy danych lub arkusz kalkulacyjny. Składa się z wierszy i kolumn, a każda kolumna może mieć inny typ danych. Możemy tworzyć DataFrame z różnych źródeł danych, takich jak pliki CSV, bazy danych, inne DataFrame itp.
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'Los Angeles', 'Chicago']}
df = pd.DataFrame(data)
print(df)
Series jest jednowymiarową strukturą danych w Pandas, reprezentującą pojedynczą kolumnę lub wiersz w DataFrame. Każda wartość w Series jest indeksowana, co umożliwia szybkie operacje na danych
import pandas as pd
numbers = pd.Series([10, 20, 30, 40, 50])
print(numbers)
Podstawowe manipulacje na danych za pomocą pandasa
import pandas as pd
df = pd.read_csv('file_name.csv') # reading data from CSV file
df.head() # displays first data rows
df.info() # displays basic information about data
df.describe() # displays basic statistics for numeric values
filtered_df = df[df['example_column'] > warunek] # filtering of rows meeting condition
column_data = df['example_column'] # selecting data from one column
subset = df[['example_column1', 'example_column2']] # selecting multiple columns
df['new_example_column'] = values # adding new column
df.dropna() # removing rows with missing values
df.drop(['example_column1', 'example_column2'], axis=1) # removing specific columns
grouped_df = df.groupby('example_column').mean() # grouping data and counting mean value
merged_df = pd.merge(df1, df2, on='key') # connecting data frames
df['example_column'] = df['example_column'].astype('new_type') # changing data in the column
sorted_df = df.sort_values(by='example_column', ascending=False) # sorting data
Pandas pozwala na obszerną manipulację analizę oraz na tworzenie wykresów podstawowych jak i zaawansowanych za pomocą innych bibliotek jak matplotlib oraz seaborn. Niestety pandas i wizualizacja danych jest zbyt obszernym tematem jak na ten skromny artykuł.
Biblioteka Requests
Biblioteka requests w Pythonie jest narzędziem, które umożliwia wysyłanie żądań HTTP do serwerów i odbieranie odpowiedzi. Jest to bardzo przydatne narzędzie do komunikacji z zewnętrznymi serwisami API, pobierania danych ze stron internetowych czy wykonania żądań HTTP.
Przykładowy get w bibliotece requests
import requests
# Sending GET request
response = requests.get('https://api.example.com/data')
# Checking response status code
if response.status_code == 200:
# Taking response data
data = response.json() # Converting JSON response to Dictionary
print(data)
else:
print('Error occured while reading data')
Biblioteka requests również pozwala nam wrzucać odpowiednie parametry w link.
params = {'key': 'value'}
response = requests.get('https://api.example.com/data', params=params)
Wysyłanie żądań POST:
params = {'key': 'value'}
response = requests.get('https://api.example.com/data', params=params)
Obsługa nagłówków:
headers = {'Authorization': 'Bearer token'}
response = requests.get('https://api.example.com/data', headers=headers)
Biblioteka requests jest bardzo elastyczna i posiada wiele zaawansowanych funkcji, które mogą być użyteczne w różnych przypadkach. Szczególnie jak połączy się wielowątkowość wraz z biblioteką requests jesteśmy w stanie stworzyć naprawdę potężne narzędzie które będzie zgarniało tysiące danych z udostępnionego API.
Framework FastAPI
FastAPI to nowoczesny framework do tworzenia aplikacji API w języku Python. Jest on oparty na standardzie ASGI (Asynchronous Server Gateway Interface), co umożliwia obsługę asynchronicznych żądań HTTP. Jest to bardzo przydatne w przypadku wysokowydajnych aplikacji internetowych. FastAPI jest szybki, łatwy do nauki i obsługuje wiele zaawansowanych funkcji, takich jak generowanie interfejsu OpenAPI (Swagger) automatycznie na podstawie kodu.
Główne cechy FastAPI
Szybkość
Dzięki wykorzystaniu asynchroniczności, FastAPI osiąga wysoką wydajność w obsłudze wielu równoczesnych żądań.
Prostota i elegancja
FastAPI korzysta z deklaratywnej składni opartej na typach danych (znanej z Pydantic), co pozwala na wygodne definiowanie endpointów API.
Automatyczna dokumentacja
FastAPI generuje automatycznie interfejs OpenAPI (dawniej znany jako Swagger), co ułatwia zarządzanie i testowanie API.
Obsługa walidacji danych
Wykorzystując Pydantic, FastAPI automatycznie waliduje i konwertuje dane wejściowe i wyjściowe.
Obsługa middleware
Możliwość dodawania middleware dla dodatkowej logiki, np. autoryzacji, logowania itp.
Prosty Przykład jak uruchomić FastAPI
Aby zainstalować FastApi w terminalu wpisujemy polecenie:
pip install fastapi uvicorn
Następnie tworzymy plik main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/add")
def add_numbers(x: int, y: int):
return {"result": x + y}
Następnie uruchamiamy aplikację za pomocą uvicorn
uvicorn main:app --reload
Teraz uruchamiamy przeglądarkę i wchodzimy pod adres http://localhost:8000/docs. Dokumentacja API zostanie automatycznie wygenerowana za pomocą Swagger.
FastAPI oferuje znacznie więcej możliwości, takich jak obsługa różnych typów żądań (POST, PUT, DELETE), obsługa plików, tworzenie zależności, testowanie automatyczne API i wiele innych. Jest to świetne narzędzie do budowy nowoczesnych i wydajnych aplikacji webowych z wykorzystaniem Pythona.
Podsumowanie
W tym artykule opisałem tematy, które stanowią fundamenty, które każdy programista Pythona powinien znać, aby efektywnie tworzyć aplikacje, analizować dane, komunikować się z serwerami oraz testować i utrzymywać kod na wysokim poziomie jakości. Zachęcam do dalszego zgłębiania opisanych zagadnień. Jeden artykuł to zdecydowanie zbyt mało by omówić wszystkie funkcjonalności i zastosowania wspomnianych bibliotek, narzędzi czy frameworków.