in programowanie

7 rzeczy, które musisz znać, żeby pisać dobry kod w Pythonie

W artykule znajdziesz 7 konstrukcji charakterystycznych dla Pythona, które sprawią, że lepiej wykorzystasz potencjał tego języka. Niektóre z nich mogą być dla Ciebie oczywiste, ale pewnie są tu też takie, które sprawią, że Twój kod stanie się bardziej zwięzły i czytelny.

1. Odwoływanie się do elementów listy

Na pierwszy rzut oka odwoływanie się do elementów listy w Pythonie nie różni się znacznie od innych języków. Listy są indeksowane od zera i wystarczy podać numer indeksu w nawiasach kwadratowych. Fajne jest jednak to, że można podawać:
  • zakresy indeksów,
  • zakres od początku do n-tego elementu listy,
  • zakres od n-tego elementu listy do końca,
  • ujemny indeks,
  • odstęp między zwracanymi elementami.
Sprawdźmy to na przykładzie. Na początek utwórzmy 10-cio elementową listę:
my_list = ['A','B','C','D','E','F','G','H','I','J']
Żeby dostać 5 element klasycznie podajemy indeks. Listy są indeksowane od zera, więc 5 element, ma indeks 4.
my_list[4]
W rezultacie otrzymamy:
'E'

1.1 Zakresy indeksów

Teraz z naszej listy pobierzmy elementy od trzeciego do szóstego.
my_list[2:6]
Wynik to: [‚C’, ‚D’, ‚E’, ‚F’]

1.2 Zakresy od początku / od końca

Jeśli chcemy dostać elementy od początku lub do końca listy, po prostu pomijamy ten indeks w zakresie. Przykład – elementy od początku listy do 5-tego.
my_list[:5]
Wynik:
['A', 'B', 'C', 'D', 'E']
Elementy od 5-tego do końca listy:
my_list[4:]
Wynik
['E', 'F', 'G', 'H', 'I', 'J']

1.3 Indeksowanie ujemne

W Pythonie możemy podawać ujemne indeksy. Jeśli chcemy otrzymać ostatni element listy piszemy:
my_list[-1]
Ujemne indeksowanie działa w ten sposób, że indeks z minusem jest odejmowany od długości listy i w ten sposób powstaje zwracany indeks.
my_list[-2]
# to, to samo co:
my_list[len(my_list) - 2]

1.4 Odstęp między zwracanymi elementami

Możemy również określić, co który element ma zostać zwrócony. Zwróćmy, co drugi element naszej listy:
my_list[::2]
Wynik
['A', 'C', 'E', 'G', 'I']
Tutaj jeszcze mały trik na odwrócenie kolejności na liście:
my_list[::-1]
Wynik:
['J', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A']

2. Porównania łańcuchowe

Małym ułatwieniem w pisaniu Pythonowego kodu są porównania łańcuchowe. Dzięki nim warunek:
if x > 3 and x < 7:
możemy zapisać krócej:
if 3 < x < 7: 

3 .Funkcja enumerate

Iterowanie po listach w Pythonie jest bardzo wygodne. Czasem jednak oprócz kolejnego elementu listy potrzebujemy również jego indeksu. Tu z pomocą przychodzi nam funkcja enumerate. Klasycznie pętle, w której potrzebujemy wartość i indeksu napisalibyśmy w ten sposób:
my_list = ['el1', 'el2', 'el3']

for i in range(len(my_list)):
    print(i, my_list[i])
Dzięki enumerate powyższą pętlę możemy zapisać w bardziej elegancki sposób:
for index, value in enumerate(my_list):
    print(index, value)

4. Przypisywanie wielu wartości do wielu zmiennych w jednej linii

Zupełnie poprawnym wyrażeniem w Pythonie jest:
a, b, c = 4, 5, 6
Gdzie to się może przydać? Postawmy przed sobą następujące zadanie:
  1. Do zmiennej x przypisujemy wartość
  2. Do zmiennej y przypisujemy wartość
  3. Zamieniamy wartości tych zmiennych tak, żeby x miała dotychczasową wartość y i odwrotnie.
Rozwiązanie bez korzystania z przypisania w jednej linii wartości do wielu zmiennych, wymaga od nas utworzenia trzeciej zmiennej, w której tymczasowo przechowamy wartość.
x = 5
y = 6
temp = x
x = y
y = temp
print(x,y)
Z zastosowaniem przypisania w jednej linii, nie potrzebujemy dodatkowej zmiennej.
x = 5
y = 6
x, y = y, x
print(x,y)

5. Typy mutowalne i niemutowalne

To informacja podstawowa, ale może zaoszczędzić czas początkujących zastanawiających się nad nietypowym zachowaniem ich kodu. Wszystko tutaj sprowadza się do tego, że typy w Pythonie dzielą się na dwie grupy:
  • mutowalne,
  • niemutowalne.
Typy mutowalne to takie, które mogą być zmieniane po utworzeniu, a niemutowalne to te, które raz utworzone nie mogą już być zmieniane. Typy mutowalne to na przykład string, integer, tuple. Za każdym razem, gdy następuje przypisanie wartości, zmienna takiego typu dostaje nowy adres w pamięci. Przykład:
a = 5
b = a
a = 10
print(b)
Zmienna b ma wartość 5. Typy niemutowalne to listy i słowniki. Przy przypisaniu zmiennej takiego typu tworzone jest odwołanie do istniejącego adresu w pamięci:
li_a = ['a', 'b']
li_b = li_a 
li_a.append('c')
print(li_b)
Zmienna li_b zawiera listę, której elementem jest ‚c’, mimo, że ‚c’ zostało dodane do listy li_a. Zmienne li_a i li_b wskazują na ten sam adres w pamięci.

6. Odwzorowywanie listy

Odwzorowywanie listy (ang. list comprehension) to bardzo wygodny sposób na tworzenie nowej listy na podstawie innej listy. Załóżmy, że mamy listę składającą się z liczb od 0 do 10.
my_list = range(10)
Nasze zadanie to utworzenie nowej listy, która będzie zawierała parzyste elementy my_list pomnożone przez 10. Klasyczne rozwiązanie sprowadza się do pętli for i sprawdzania warunku
result_list = []
for el in my_list:
    if el % 2 == 0:
        result_list.append(el*10)
print(result_list)
Dzięki list comprehension iterowanie po elementach listy i sprawdzanie warunku możemy zapisać w jednej linii:
result_list = [el * 10 for el in my_list if el % 2 == 0]
print(result_list)

7. Funkcje lambda

Ostatnią przydatną rzeczą, o której dzisiaj wspomnę jest możliwość tworzenia nienazwanych funkcji. Jest ona przydatna, na przykład gdy chcemy przekazać funkcję jako parametr do innej funkcji. Przykład:
print_greater = lambda x, y: print(x) if x >= y else print(y)
print_greater(10, 20)
daje ten sam efekt, co:
def print_greater(x,y):
    if x >= y:
        print(x)
    else:
        print(y)

print_greater(10, 20)
W powyższym przykładzie funkcje lambda i tak nazywamy, co nie ma większego sensu, ale pokazuje jak wygląda składnia funkcji lambda. Lambdy przydatne są wszędzie tam gdzie chcemy skorzystać z nienazwanej funkcji i jej wcześniejsza deklaracja byłaby niepotrzebną stratą czasu.

Podsumowanie

Mam nadzieję, że przekonasz się do stosowania tych konstrukcji w swoim kodzie. Moim zdaniem skracają one kod i czynią go bardziej eleganckim i zwięzłym. Są też tacy, którzy twierdzą, że dzieje się to kosztem łatwości interpretacji. Jak w wielu kwestiach trzeba tutaj znaleźć złoty środek. Ja korzystam z w/w konstrukcji w uzasadnionych przypadkach, ale staram się nie przekombinować.

Write a Comment

Comment

  1. Czyli proste podstawy :)) ale fajnie że ktoś porusza temat pythona, ciężko było mi znaleźć jakieś fajny blog. Czekam na następne wpisy 🙂