Umiejętności programowania w Pythonie są coraz bardziej pożądane. Aby pomóc ci je rozwinąć, zebraliśmy 30 fajnych trików w Pythonie, które możesz wykorzystać, by ulepszyć swój kod. Ucz się jednego dziennie przez kolejne 30 dni i zajrzyj do naszego wpisu o najlepszych praktykach w Pythonie, żeby mieć pewność, że twój kod jest na najwyższym poziomie.
Jeśli twoje umiejętności w Pythonie wymagają odświeżenia, możesz je też podszlifować dzięki naszej ścieżce umiejętności Python Programming.
Triki dotyczące sekwencji i struktur danych
#1 Wycinki (slicing)
a ="Hello World!"print(a[::-1])"""
!dlroW olleH
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Wycinki to funkcja w Pythonie oparta na indeksowaniu, która pozwala uzyskać dostęp do podzbioru sekwencji. Indeks to po prostu pozycja elementu w sekwencji. Jeśli typ sekwencji jest mutowalny, możesz użyć wycinków do wyodrębniania i modyfikowania danych.
Uwaga: Wycinków można używać także na sekwencjach niemutowalnych, ale próba modyfikacji wycinka spowoduje TypeError.
Format wycinków to: sequence[start:stop:step]. Jeśli nie podasz wartości w parametrach start, stop i step, użyte zostaną domyślne. Domyślne to:
„start” domyślnie 0
„stop” domyślnie długość sekwencji
„step” domyślnie 1, jeśli nie został określony.
Przy sequence[start:stop] zwrócone zostaną elementy od indeksu początkowego do stop - 1 (indeks stop nie jest wliczany).
Możemy też przekazać ujemne indeksy, co można wykorzystać do odwrócenia sekwencji. Na przykład w liście 4‑elementowej indeks 0 to także indeks -4, a ostatni indeks to również -1. W powyższym przykładzie zastosowano to w parametrze step sekwencji. W efekcie napis został wypisany od końca, od ostatniego elementu do indeksu 0.
#2 Podmiana w miejscu / jednoczesne przypisanie
a =10
b =5print(f"First: {a, b}")"""
First: (10, 5)
"""
a, b = b, a +2print(f"Second: {a, b}")"""
Second: (5, 12)
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Połączenie automatycznego pakowania i rozpakowywania daje technikę znaną jako jednoczesne przypisanie. Możemy jej używać do przypisania serii wartości do serii zmiennych.
#3 Lista vs. krotka (tuple)
import sys
a =[1,2,3,4,5]
b =(1,2,3,4,5)print(f"List size: {sys.getsizeof(a)} bytes")print(f"Tuple size: {sys.getsizeof(b)} bytes")"""
List size: 52 bytes
Tuple size: 40 bytes
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Większość programistów Pythona zna strukturę danych listy. Tego samego nie można powiedzieć o krotkach. Obie są iterowalne, pozwalają na indeksowanie i przechowywanie heterogenicznych typów danych. Są jednak sytuacje, w których lepiej wybrać krotkę zamiast listy.
Przede wszystkim listy są mutowalne, co oznacza, że możemy je dowolnie modyfikować:
Krotki są natomiast niemutowalne, więc próba ich modyfikacji spowoduje TypeError.
Z tego powodu krotki są bardziej pamięciooszczędne, ponieważ Python może przydzielić dokładnie tyle pamięci, ile potrzeba na dane. W przypadku listy trzeba zarezerwować dodatkową pamięć na wypadek rozszerzenia – to tzw. dynamiczna alokacja pamięci.
TL;DR: W scenariuszach, gdy nie chcesz, by dane się zmieniały, dla oszczędności pamięci preferuj krotkę zamiast listy. Krotki są też szybsze od list.
a =[x *2for x inrange(10)]
b =(x *2for x inrange(10))print(a)print(b)"""
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
<generator object <genexpr> at 0x7f61f8808b50>
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Wyrażenia listowe to „pythoniczny” sposób tworzenia listy z innego iterowalnego — jest znacznie szybszy niż pętla for. A co się stanie, jeśli przypadkowo zmienisz nawiasy z [] na ()? Otrzymasz obiekt generatora.
W Pythonie okrągłe nawiasy z logiką wyrażenia listowego tworzą tzw. obiekt generatora. Generatory to szczególny rodzaj iterowalnych. W przeciwieństwie do list nie przechowują elementów, lecz instrukcje generowania kolejnych elementów oraz bieżący stan iteracji.
Każdy element jest generowany na żądanie dzięki technice zwanej leniową ewaluacją. Główna zaleta tego triku z generatorem to mniejsze zużycie pamięci, ponieważ cała sekwencja nie jest budowana naraz.
#5 Aliasowanie
a =[1,2,3,4,5]
b = a
# Change the 4th index in b
b[4]=7print(id(a))print(id(b))print(a)# Remember we did not explicitly make changes to a."""
15136008
15136008
[1, 2, 3, 4, 7]
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Python to język zorientowany obiektowo — wszystko jest obiektem. Przypisanie obiektu do identyfikatora tworzy referencję do obiektu.
Gdy przypiszemy jeden identyfikator do drugiego, otrzymujemy dwa identyfikatory wskazujące ten sam obiekt. To zjawisko to aliasowanie. Zmiany w jednym aliasie wpłyną na drugi. Czasem jest to pożądane, ale często zaskakuje.
Jednym ze sposobów obejścia jest unikanie aliasowania przy obiektach mutowalnych. Innym rozwiązaniem jest utworzenie klona oryginalnego obiektu zamiast referencji.
Kolejny trik to najprostszy sposób sprawdzenia, czy twoja struktura danych jest pusta — użyj operatora not. Wbudowany not to operator logiczny, który zwraca True, jeśli wyrażenie nie jest prawdziwe, w przeciwnym razie False — odwraca wartość logiczną wyrażeń i obiektów.
Czasem musimy sformatować napis; Python 3.6 wprowadził fajną funkcję zwaną f‑stringami, która to upraszcza. Warto zrozumieć, jak formatowano napisy wcześniej, by lepiej docenić nową metodę.
Tak kiedyś formatowano napisy:
first_name ="John"
age =19print("Hi, I'm {} and I'm {} years old!".format(first_name, age))"""
Hi, I'm John and I'm 19 years old!
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Dość często używa się instrukcji print bez definiowania parametrów opcjonalnych. W efekcie wielu Pythonistów nie wie, że można w pewnym stopniu kontrolować wyjście.
Jednym z parametrów opcjonalnych, który możemy zmienić, jest end. Parametr end określa, co ma się pojawić na końcu wywołania instrukcji print.
Domyślną wartością end jest "\n", czyli rozpoczęcie nowej linii. W powyższym kodzie zmieniliśmy to na spację. Dzięki temu wszystkie elementy listy zostały wypisane w jednym wierszu.
#9 Dodawanie do krotki
a =(1,2,[1,2,3])
a[2].append(4)print(a)"""
(1, 2, [1, 2, 3, 4])
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Wiemy już, że krotki są niemutowalne — zobacz trik #3 Lista vs. krotki. Próba zmiany stanu krotki spowoduje TypeError. Ale jeśli potraktujesz krotkę jako sekwencję nazw z powiązaniami do obiektów, których nie można zmieniać, możesz spojrzeć na to inaczej.
Dwa pierwsze elementy naszej krotki to liczby całkowite — są niemutowalne. Ostatni element to lista, obiekt mutowalny w Pythonie.
Jeśli potraktujemy naszą listę jako kolejną nazwę w sekwencji z niezmiennym powiązaniem do obiektu, to zauważymy, że lista nadal może być modyfikowana wewnątrz krotki.
Czy polecamy robić tak w praktyce? Raczej nie, ale to jedna z rzeczy, które warto wiedzieć!
#10 Łączenie słowników
a ={"a":1,"b":2}
b ={"c":3,"d":4}
a_and_b = a | b
print(a_and_b)"""
{"a": 1, "b": 2, "c": 3, "d": 4}
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
W powyższym kodzie widać tzw. operator trójargumentowy — nazywany też wyrażeniem warunkowym. Używamy go do oceny czegoś zależnie od tego, czy warunek jest True, czy False.
Można to było zapisać także tak:
condition =Trueif condition:
name ="John"else:
name ="Doe"print(name)"""
John
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Najprościej usunąć duplikaty z listy, konwertując ją na zbiór (a następnie z powrotem na listę, jeśli chcesz).
Pod względem mutowalności zbiory i listy są w Pythonie dość podobne. Możemy dodawać i usuwać elementy w obu strukturach, ale wciąż są one skrajnie różne.
Listy są uporządkowane, indeksowane od zera i mutowalne. Zbiory są nieuporządkowane i nieindeksowane. Elementy w zbiorze muszą być typu niemutowalnego, choć sam zbiór jest mutowalny — próba pobrania elementu przez indeks lub jego modyfikacji spowoduje błąd.
Inna kluczowa różnica to fakt, że zbiory nie mogą zawierać duplikatów. To właśnie pozwoliło nam usunąć powtórzenia z listy.
#13 Samotny podkreślnik
>>> print(_)
Traceback (most recent call last):
File "<stdin>", line 1, in<module>>>>1 + 23>>> print(_)3Obsługiwane przez
Podkreślnik (_) to legalny identyfikator w Pythonie, więc można go użyć do referencji obiektu. Ma jednak też inne zadanie: przechowuje wynik ostatniej ewaluacji.
Dokumentacja mówi, że „interaktywny interpreter udostępnia wynik ostatniej ewaluacji w zmiennej _. (Przechowywany jest w module builtins, obok funkcji wbudowanych jak print).”
Ponieważ nie przypisaliśmy wcześniej żadnego obiektu do podkreślnika, w pierwszej linii dostaliśmy błąd. Gdy obliczyliśmy wynik 1 + 2, interpreter zapisał rezultat pod identyfikatorem _ za nas.
#14 Podkreślnik do ignorowania wartości
for _ inrange(100):print("The index doesn't matter")"""
The index doesn't matter
The index doesn't matter
...
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
W triku #13 odkryliśmy, że interaktywny interpreter udostępnia ostatni wynik ewaluacji pod identyfikatorem (_), ale to nie jedyny przypadek użycia.
Można go też używać do reprezentowania obiektów, które nas nie interesują lub których później nie wykorzystamy. To ważne, bo użycie identyfikatora zamiast podkreślnika (_) spowoduje błąd F841 podczas lintowania programu. Błąd F841 informuje, że lokalna zmienna została przypisana, ale nieużyta — to zła praktyka.
Kontynuując temat podkreślnika (_), inny jego cel to unikanie konfliktów ze słowami kluczowymi Pythona.
PEP 8 wspomina, że końcowy podkreślnik (_) powinien być „używany zwyczajowo, by uniknąć konfliktów ze słowami kluczowymi Pythona.” Dodaje też, że „zazwyczaj lepiej dodać pojedynczy końcowy podkreślnik niż używać skrótu lub zniekształconej pisowni. Dlatego list_ jest lepsze niż lst.”
#16 Podkreślnik na początku
classExample:def__init__(self):
self._internal =2
self.external =20Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Często doświadczeni programiści Pythona poprzedzają identyfikator lub nazwę metody podkreślnikiem — i to z dobrego powodu.
Podkreślnik przed nazwą zmiennej lub metody ma ukryte znaczenie: ta zmienna lub metoda jest przeznaczona wyłącznie do użytku wewnętrznego. To w gruncie rzeczy zastrzeżenie dla innych programistów, opisane w PEP 8, ale nieegzekwowane przez Pythona. Zatem wiodące podkreślniki to słaby wskaźnik.
W przeciwieństwie do Javy Python nie ma silnego rozróżnienia między zmiennymi prywatnymi i publicznymi. Innymi słowy, ma to znaczenie tylko dlatego, że społeczność Pythona się na to umówiła. Ich użycie nie wpływa na zachowanie programu.
#17 Podkreślnik jako separator
Oto ostatni tip o podkreślnikach; do tej pory omówiliśmy trzy różne przypadki użycia, ale możesz sprawdzić nasz poradnik, by dowiedzieć się więcej o roli podkreślnika (_) w Pythonie.
Inny sposób użycia podkreślnika to wizualny separator grup cyfr w literałach całkowitych, zmiennoprzecinkowych i zespolonych — wprowadzony w Pythonie 3.6.
Chodziło o poprawę czytelności długich literałów lub takich, które powinny być wyraźnie podzielone na części — więcej w PEP 515.
Triki stylu i składni
#18 __name__ == „__main__”
if __name__ =="__main__":print("Read on to understand what is going on when you do this.")"""
print("Read on to understand what is going on when you do this.")
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Jest duża szansa, że widziałeś tę składnię w wielu programach w Pythonie; Python używa specjalnej nazwy "__main__" i przypisuje ją do identyfikatora __name__, jeśli uruchamiany plik Pythona jest głównym programem.
Jeśli zaimportujemy moduł pokazany na zrzucie do innego modułu (pliku Pythona) i uruchomimy tamten plik, wyrażenie w naszym kodzie będzie fałszywe. Dzieje się tak, bo przy imporcie z innego modułu identyfikator __name__ jest ustawiany na nazwę modułu (pliku).
#19 Metoda „setdefault”
import pprint
text ="It's the first of April. It's still cold in the UK. But I'm going to the museum so it should be a wonderful day"
counts ={}for word in text.split():
counts.setdefault(word,0)
counts[word]+=1
pprint.pprint(counts)"""
{'April.': 1,
'But': 1,
"I'm": 1,
"It's": 2,
'UK.': 1,
'a': 1,
'be': 1,
'cold': 1,
'day': 1,
'first': 1,
'going': 1,
'in': 1,
'it': 1,
'museum': 1,
'of': 1,
'should': 1,
'so': 1,
'still': 1,
'the': 3,
'to': 1,
'wonderful': 1}
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Bardziej zwięzłym sposobem jest użycie metody setdefault() na obiekcie słownika.
Pierwszy argument metody to klucz, którego szukamy. Drugi argument to wartość, którą ustawimy, jeśli klucza nie ma jeszcze w słowniku — jeśli klucz istnieje, metoda zwróci jego wartość, więc nie zostanie zmieniona.
Triki dotyczące struktury programu
#20 Dopasowanie regex
import re
number = re.compile(r"(0)?(\+44)?\d{10}")
num_1 = number.search("My number is +447999999999")
num_2 = number.search("My number is 07999999999")print(num_1.group())print(num_2.group())"""
'+447999999999'
'07999999999'
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Wyrażenia regularne pozwalają określać wzorce tekstu do wyszukania; większość osób wie, że można szukać rzeczy skrótem CTRL + F (Windows), ale jeśli nie wiesz dokładnie, czego szukasz, jak to znaleźć? Odpowiedź: szukaj wzorców.
Na przykład numery w UK mają podobny wzorzec: zaczynają się od zera i dziesięciu cyfr lub od +44 zamiast zera i dziesięciu cyfr — drugi wariant to format międzynarodowy.
Regex to ogromna oszczędność czasu. Gdybyśmy mieli zakodować reguły wykrywania przypadków z obrazka zamiast użyć regex, mogłoby to zająć 10+ linii kodu.
Nauka działania wyrażeń regularnych jest ważna nawet, jeśli nie piszesz kodu. Większość nowoczesnych edytorów i procesorów tekstu pozwala używać regexów w funkcjach znajdź i zamień.
#21 Operator „|” w regex
import re
heros = re.compile(r"Super(man|woman|human)")
h1 = heros.search("This will find Superman")
h2 = heros.search("This will find Superwoman")
h3 = heros.search("This will find Superhuman")print(h1.group())print(h2.group())print(h3.group())"""
Superman
Superwoman
Superhuman
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Wyrażenia regularne mają specjalny znak pipe (|), który pozwala dopasować jedno z wielu wyrażeń i można go używać w dowolnym miejscu. To super przydatne przy kilku podobnych wzorcach.
Na przykład „Superman”, „Superwoman” i „Superhuman” mają ten sam prefiks. Możesz więc użyć pipe, by zachować część wzorca, która się powtarza, i zmieniać tę, która ma się różnić. Znowu oszczędzasz cenny czas.
Uważaj na haczyk: jeśli wszystkie wyrażenia, które chcesz dopasować, występują w tym samym tekście, zwrócone zostanie pierwsze dopasowanie — tzn. „An example text containing Superwoman, Superman, Superhuman” zwróci Superwoman.
#22 Parametr „sep” funkcji print()
day ="04"
month ="10"
year ="2022"print(day, month, year)print(day, month, year, sep ="")print(day, month, year, sep =".")"""
04 10 2022
04/10/2022
04.10.2022
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Liczba programistów Pythona, którzy nie znają pełnych możliwości funkcji print(), jest zaskakująca; jeśli „Hello World” było twoim pierwszym programem, print() zapewne było jedną z pierwszych funkcji wbudowanych, które poznałeś. Używamy print() do wyświetlania sformatowanych komunikatów, ale potrafi ono znacznie więcej.
W powyższym kodzie pokazaliśmy różne sposoby wyświetlenia formatu. Parametr sep to opcjonalny argument funkcji print(), który pozwala określić, jak rozdzielać obiekty, jeśli przekażemy ich więcej niż jeden.
Domyślnie są rozdzielane spacją, ale zmieniliśmy to w naszych wywołaniach — raz ustawiając sep na "", a innym razem na ".".
#23 Funkcje lambda
defsquare(num:int)->int:return num **2print(f"Function call: {square(4)}")"""
Function call: 16
"""
square_lambda =lambda x: x**2print(f"Lambda function: {square_lambda(4)}")"""
Lambda functional: 16
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Funkcje lambda wprowadzają cię na bardziej średnio‑zaawansowany/zaawansowany poziom możliwości Pythona — naucz się Intermediate Python na tym kursie. Na pierwszy rzut oka wyglądają skomplikowanie, ale są dość proste.
W przykładzie użyliśmy jednego argumentu, ale moglibyśmy użyć wielu:
square =lambda a, b: a ** b
print(f"Lambda function: {square(4,2)}")"""
16
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
W istocie słowo kluczowe lambda pozwala tworzyć małe, ograniczone, anonimowe funkcje w jednej linii. Zachowują się jak zwykłe funkcje zadeklarowane słowem def, z tą różnicą, że nie mają nazwy.
#24 Metoda „swapcase”
string ="SoMe RaNDoM sTriNg"print(string.swapcase())"""
sOmE rAndOm StRInG
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Metoda swapcase() zastosowana do napisu pozwala zamienić wielkie litery na małe i odwrotnie w jednej linii kodu. Zastosowań nie ma wiele, ale warto wiedzieć.
#25 Metoda „isalnum”
password ="ABCabc123"print(password.isalnum())"""
True
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Załóżmy, że tworzysz program, w którym użytkownicy podają hasło, a ono musi zawierać kombinację liter i cyfr. Da się to sprawdzić jedną linią, wywołując isalnum() na instancji napisu.
Metoda sprawdza, czy wszystkie znaki są alfanumeryczne (A‑Za‑z, 0‑9). Spacja lub symbol (!#%$&? itd.) zwróci False.
#26 Obsługa wyjątków
defget_ration(x:int, y:int)->int:try:
ratio = x/y
except ZeroDivisionError:
y = y +1
ratio = x/y
return ratio
print(get_ration(x=400, y=0))"""
400.0
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Programy w Pythonie kończą działanie, gdy napotkają błąd.
Czasem nie chcemy takiego zachowania, np. gdy z naszym kodem wchodzi w interakcję użytkownik końcowy. Jak źle by było, gdyby program zakończył się przedwcześnie?
Istnieje kilka podejść do przypadków wyjątkowych. Większość programistów Pythona kieruje się zasadą, że łatwiej jest prosić o wybaczenie niż o pozwolenie. Oznacza to, że wolą przechwycić zgłoszony błąd, zapewniając kontekst zdolny do obsłużenia wyjątku. Idea jest taka, że nie ma sensu tracić czasu na zabezpieczanie się przed wszystkimi możliwymi wyjątkami.
Ale to ma sens tylko wtedy, gdy istnieje mechanizm radzenia sobie z problemem po jego wystąpieniu.
Używamy *args i **kwargs jako parametrów funkcji, gdy nie wiemy, ile zmiennych powinna ona przyjąć.
Parametr *args pozwala przekazać zmienną liczbę argumentów pozycyjnych (tj. bez nazw). Z kolei **kwargs umożliwia przekazanie dowolnej liczby argumentów nazwanych.
W rzeczywistości słowa *args i **kwargs nie są magiczne: magia tkwi w gwiazdkach (*). Moglibyśmy użyć dowolnego słowa po gwiazdkach, ale zwyczaj używania args i kwargs jest powszechny i egzekwowany wśród programistów Pythona.
#29 Wielokropek (Ellipsis)
print(...)"""
Ellipsis
"""defsome_function():...# Alternative solutiondefanother_function():passObsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Nasz ostatni trik to wyrażenia listowe, elegancki sposób tworzenia listy z innej sekwencji. Pozwalają wykonywać złożoną logikę i filtrowanie, jak w powyższym kodzie.
Można to osiągnąć też innymi sposobami; np. moglibyśmy użyć funkcji lambda tak:
even_numbers =list(filter(lambda x: x %2==0and x !=0,range(10)))print(even_numbers)"""
[0, 2, 4, 6, 8]
"""Obsługiwane przez
Edytor nauki przez przykład, naciśnij Tab, aby wejść. Naciśnij Escape, a następnie Tab lub Shift+Tab, aby wyjść.
Ale wielu Pythonistów uzna to rozwiązanie za mniej czytelne niż wyrażenie listowe.
FAQs
Jaki trik w Pythonie jest najprzydatniejszy dla początkujących?⌄
F‑stringi są prawdopodobnie najbardziej przydatne na start. Sprawiają, że formatowanie napisów jest szybsze, czytelniejsze i trudniej w nim o błąd w porównaniu ze starszymi podejściami jak .format().
Jaki jest najszybszy sposób na zamianę wartości dwóch zmiennych w Pythonie?⌄
Użyj jednoczesnego przypisania: a, b = b, a. Nie potrzeba zmiennej tymczasowej — Python najpierw w pełni oblicza prawą stronę, a potem przypisuje.
Jak połączyć dwa słowniki w jednej linii?⌄
W Pythonie 3.9+ użyj operatora |: merged = dict_a | dict_b. W starszych wersjach użyj {**dict_a, **dict_b}.
Jaka jest różnica między *args a **kwargs?⌄
*args zbiera dodatkowe argumenty pozycyjne do krotki. **kwargs zbiera dodatkowe argumenty nazwane do słownika. Magia tkwi w operatorach * i **, nie w samych nazwach — możesz je nazwać dowolnie.
Jak sprawdzić, czy lista w Pythonie jest pusta?⌄
Użyj operatora not: if not my_list:. To bardziej „pythoniczne” niż sprawdzanie len(my_list) == 0.
Jaka jest różnica między wyrażeniem listowym a generatorem?⌄
Wyrażenie listowe (nawiasy kwadratowe) buduje całą listę w pamięci naraz. Generator (nawiasy okrągłe) produkuje wartości po jednej na żądanie, zużywając znacznie mniej pamięci dla dużych sekwencji.
Kiedy używać operatora trójargumentowego?⌄
Używaj go do prostych, jednolinijkowych warunków, gdzie oba wyniki są krótkie i czytelne: name = "John" if condition else "Doe". Przy bardziej złożonych przypadkach zwykły blok if/else jest czytelniejszy.
Jaki jest najprostszy sposób usunięcia duplikatów z listy?⌄
Opakuj ją w set() i skonwertuj z powrotem: list(set(my_list)). Pamiętaj tylko, że zbiory są nieuporządkowane, więc oryginalna kolejność nie zostanie zachowana.
Umiejętności programowania w Pythonie są coraz bardziej pożądane. Aby pomóc ci je rozwinąć, zebraliśmy 30 fajnych trików w Pythonie, które możesz wykorzystać, by ulepszyć swój kod. Ucz się jednego dziennie przez kolejne 30 dni i zajrzyj do naszego wpisu o najlepszych praktykach w Pythonie, żeby mieć pewność, że twój kod jest na najwyższym poziomie.
Jeśli twoje umiejętności w Pythonie wymagają odświeżenia, możesz je też podszlifować dzięki naszej ścieżce umiejętności Python Programming.
Triki dotyczące sekwencji i struktur danych
#1 Wycinki (slicing)
Wycinki to funkcja w Pythonie oparta na indeksowaniu, która pozwala uzyskać dostęp do podzbioru sekwencji. Indeks to po prostu pozycja elementu w sekwencji. Jeśli typ sekwencji jest mutowalny, możesz użyć wycinków do wyodrębniania i modyfikowania danych.
Uwaga: Wycinków można używać także na sekwencjach niemutowalnych, ale próba modyfikacji wycinka spowoduje TypeError.
Format wycinków to: sequence[start:stop:step]. Jeśli nie podasz wartości w parametrach start, stop i step, użyte zostaną domyślne. Domyślne to:
Przy sequence[start:stop] zwrócone zostaną elementy od indeksu początkowego do stop - 1 (indeks stop nie jest wliczany).
Możemy też przekazać ujemne indeksy, co można wykorzystać do odwrócenia sekwencji. Na przykład w liście 4‑elementowej indeks 0 to także indeks -4, a ostatni indeks to również -1. W powyższym przykładzie zastosowano to w parametrze step sekwencji. W efekcie napis został wypisany od końca, od ostatniego elementu do indeksu 0.
#2 Podmiana w miejscu / jednoczesne przypisanie
Jeśli twoje pierwsze wrażenie było takie, że wartość b wyniesie 7 zamiast 12, wpadłeś w pułapkę podmiany w miejscu.
W Pythonie możemy rozpakować iterowalne do zmiennych w jednym przypisaniu używając automatycznego rozpakowywania. Na przykład:
Możemy też zebrać kilka wartości do jednej zmiennej, używając * – ten trik w Pythonie nazywa się pakowaniem. Poniżej przykład pakowania.
Połączenie automatycznego pakowania i rozpakowywania daje technikę znaną jako jednoczesne przypisanie. Możemy jej używać do przypisania serii wartości do serii zmiennych.
#3 Lista vs. krotka (tuple)
Większość programistów Pythona zna strukturę danych listy. Tego samego nie można powiedzieć o krotkach. Obie są iterowalne, pozwalają na indeksowanie i przechowywanie heterogenicznych typów danych. Są jednak sytuacje, w których lepiej wybrać krotkę zamiast listy.
Przede wszystkim listy są mutowalne, co oznacza, że możemy je dowolnie modyfikować:
Krotki są natomiast niemutowalne, więc próba ich modyfikacji spowoduje TypeError.
Z tego powodu krotki są bardziej pamięciooszczędne, ponieważ Python może przydzielić dokładnie tyle pamięci, ile potrzeba na dane. W przypadku listy trzeba zarezerwować dodatkową pamięć na wypadek rozszerzenia – to tzw. dynamiczna alokacja pamięci.
TL;DR: W scenariuszach, gdy nie chcesz, by dane się zmieniały, dla oszczędności pamięci preferuj krotkę zamiast listy. Krotki są też szybsze od list.
Dowiedz się więcej o strukturach danych w Pythonie w tym poradniku.
#4 Generatory
Wyrażenia listowe to „pythoniczny” sposób tworzenia listy z innego iterowalnego — jest znacznie szybszy niż pętla for. A co się stanie, jeśli przypadkowo zmienisz nawiasy z [] na ()? Otrzymasz obiekt generatora.
W Pythonie okrągłe nawiasy z logiką wyrażenia listowego tworzą tzw. obiekt generatora. Generatory to szczególny rodzaj iterowalnych. W przeciwieństwie do list nie przechowują elementów, lecz instrukcje generowania kolejnych elementów oraz bieżący stan iteracji.
Każdy element jest generowany na żądanie dzięki technice zwanej leniową ewaluacją. Główna zaleta tego triku z generatorem to mniejsze zużycie pamięci, ponieważ cała sekwencja nie jest budowana naraz.
#5 Aliasowanie
Python to język zorientowany obiektowo — wszystko jest obiektem. Przypisanie obiektu do identyfikatora tworzy referencję do obiektu.
Gdy przypiszemy jeden identyfikator do drugiego, otrzymujemy dwa identyfikatory wskazujące ten sam obiekt. To zjawisko to aliasowanie. Zmiany w jednym aliasie wpłyną na drugi. Czasem jest to pożądane, ale często zaskakuje.
Jednym ze sposobów obejścia jest unikanie aliasowania przy obiektach mutowalnych. Innym rozwiązaniem jest utworzenie klona oryginalnego obiektu zamiast referencji.
Najprostszy klon uzyskasz przez wycinek:
To utworzy nową referencję do obiektu listy pod identyfikatorem b.
Możesz też użyć innych rozwiązań, np. wywołać list(a) przy przypisaniu do innego identyfikatora albo metodę copy().
#6 Operator „not”
Kolejny trik to najprostszy sposób sprawdzenia, czy twoja struktura danych jest pusta — użyj operatora not. Wbudowany not to operator logiczny, który zwraca True, jeśli wyrażenie nie jest prawdziwe, w przeciwnym razie False — odwraca wartość logiczną wyrażeń i obiektów.
Możesz go też spotkać w instrukcji if:
Gdy a jest True, operator not zwróci False, i odwrotnie.
Na początku bywa to mylące — spróbuj sam.
Triki dotyczące napisów i wyjścia
#7 F‑stringi
Czasem musimy sformatować napis; Python 3.6 wprowadził fajną funkcję zwaną f‑stringami, która to upraszcza. Warto zrozumieć, jak formatowano napisy wcześniej, by lepiej docenić nową metodę.
Tak kiedyś formatowano napisy:
Nowy sposób jest zasadniczo szybszy, czytelniejszy, zwięźlejszy i trudniej się w nim pomylić.
Inne zastosowanie f‑stringów to wypisanie nazwy identyfikatora wraz z wartością. Dodano to w Pythonie 3.8.
Zajrzyj do poradnika F‑string Formatting in Python, by dowiedzieć się więcej.
#8 Parametr „end” funkcji print()
Dość często używa się instrukcji print bez definiowania parametrów opcjonalnych. W efekcie wielu Pythonistów nie wie, że można w pewnym stopniu kontrolować wyjście.
Jednym z parametrów opcjonalnych, który możemy zmienić, jest end. Parametr end określa, co ma się pojawić na końcu wywołania instrukcji print.
Domyślną wartością end jest "\n", czyli rozpoczęcie nowej linii. W powyższym kodzie zmieniliśmy to na spację. Dzięki temu wszystkie elementy listy zostały wypisane w jednym wierszu.
#9 Dodawanie do krotki
Wiemy już, że krotki są niemutowalne — zobacz trik #3 Lista vs. krotki. Próba zmiany stanu krotki spowoduje TypeError. Ale jeśli potraktujesz krotkę jako sekwencję nazw z powiązaniami do obiektów, których nie można zmieniać, możesz spojrzeć na to inaczej.
Dwa pierwsze elementy naszej krotki to liczby całkowite — są niemutowalne. Ostatni element to lista, obiekt mutowalny w Pythonie.
Jeśli potraktujemy naszą listę jako kolejną nazwę w sekwencji z niezmiennym powiązaniem do obiektu, to zauważymy, że lista nadal może być modyfikowana wewnątrz krotki.
Czy polecamy robić tak w praktyce? Raczej nie, ale to jedna z rzeczy, które warto wiedzieć!
#10 Łączenie słowników
W Pythonie 3.9 i nowszych można łączyć słowniki za pomocą | (bitowe OR). W zasadzie tyle — to po prostu znacznie czytelniejsze rozwiązanie!
Triki stylu i składni
#11 Operator trójargumentowy / wyrażenia warunkowe
W powyższym kodzie widać tzw. operator trójargumentowy — nazywany też wyrażeniem warunkowym. Używamy go do oceny czegoś zależnie od tego, czy warunek jest True, czy False.
Można to było zapisać także tak:
Choć oba zapisy dają ten sam wynik, zauważ, że zapis trójargumentowy pozwala napisać kod krótszy i jaśniejszy. To bardziej „pythoniczny” sposób.
#12 Usuwanie duplikatów z list
Najprościej usunąć duplikaty z listy, konwertując ją na zbiór (a następnie z powrotem na listę, jeśli chcesz).
Pod względem mutowalności zbiory i listy są w Pythonie dość podobne. Możemy dodawać i usuwać elementy w obu strukturach, ale wciąż są one skrajnie różne.
Listy są uporządkowane, indeksowane od zera i mutowalne. Zbiory są nieuporządkowane i nieindeksowane. Elementy w zbiorze muszą być typu niemutowalnego, choć sam zbiór jest mutowalny — próba pobrania elementu przez indeks lub jego modyfikacji spowoduje błąd.
Inna kluczowa różnica to fakt, że zbiory nie mogą zawierać duplikatów. To właśnie pozwoliło nam usunąć powtórzenia z listy.
#13 Samotny podkreślnik
Podkreślnik (_) to legalny identyfikator w Pythonie, więc można go użyć do referencji obiektu. Ma jednak też inne zadanie: przechowuje wynik ostatniej ewaluacji.
Dokumentacja mówi, że „interaktywny interpreter udostępnia wynik ostatniej ewaluacji w zmiennej _. (Przechowywany jest w module builtins, obok funkcji wbudowanych jak print).”
Ponieważ nie przypisaliśmy wcześniej żadnego obiektu do podkreślnika, w pierwszej linii dostaliśmy błąd. Gdy obliczyliśmy wynik 1 + 2, interpreter zapisał rezultat pod identyfikatorem _ za nas.
#14 Podkreślnik do ignorowania wartości
W triku #13 odkryliśmy, że interaktywny interpreter udostępnia ostatni wynik ewaluacji pod identyfikatorem (_), ale to nie jedyny przypadek użycia.
Można go też używać do reprezentowania obiektów, które nas nie interesują lub których później nie wykorzystamy. To ważne, bo użycie identyfikatora zamiast podkreślnika (_) spowoduje błąd F841 podczas lintowania programu. Błąd F841 informuje, że lokalna zmienna została przypisana, ale nieużyta — to zła praktyka.
#15 Podkreślnik na końcu
Kontynuując temat podkreślnika (_), inny jego cel to unikanie konfliktów ze słowami kluczowymi Pythona.
PEP 8 wspomina, że końcowy podkreślnik (_) powinien być „używany zwyczajowo, by uniknąć konfliktów ze słowami kluczowymi Pythona.” Dodaje też, że „zazwyczaj lepiej dodać pojedynczy końcowy podkreślnik niż używać skrótu lub zniekształconej pisowni. Dlatego list_ jest lepsze niż lst.”
#16 Podkreślnik na początku
Często doświadczeni programiści Pythona poprzedzają identyfikator lub nazwę metody podkreślnikiem — i to z dobrego powodu.
Podkreślnik przed nazwą zmiennej lub metody ma ukryte znaczenie: ta zmienna lub metoda jest przeznaczona wyłącznie do użytku wewnętrznego. To w gruncie rzeczy zastrzeżenie dla innych programistów, opisane w PEP 8, ale nieegzekwowane przez Pythona. Zatem wiodące podkreślniki to słaby wskaźnik.
W przeciwieństwie do Javy Python nie ma silnego rozróżnienia między zmiennymi prywatnymi i publicznymi. Innymi słowy, ma to znaczenie tylko dlatego, że społeczność Pythona się na to umówiła. Ich użycie nie wpływa na zachowanie programu.
#17 Podkreślnik jako separator
Oto ostatni tip o podkreślnikach; do tej pory omówiliśmy trzy różne przypadki użycia, ale możesz sprawdzić nasz poradnik, by dowiedzieć się więcej o roli podkreślnika (_) w Pythonie.
Inny sposób użycia podkreślnika to wizualny separator grup cyfr w literałach całkowitych, zmiennoprzecinkowych i zespolonych — wprowadzony w Pythonie 3.6.
Chodziło o poprawę czytelności długich literałów lub takich, które powinny być wyraźnie podzielone na części — więcej w PEP 515.
Triki stylu i składni
#18 __name__ == „__main__”
Jest duża szansa, że widziałeś tę składnię w wielu programach w Pythonie; Python używa specjalnej nazwy "__main__" i przypisuje ją do identyfikatora __name__, jeśli uruchamiany plik Pythona jest głównym programem.
Jeśli zaimportujemy moduł pokazany na zrzucie do innego modułu (pliku Pythona) i uruchomimy tamten plik, wyrażenie w naszym kodzie będzie fałszywe. Dzieje się tak, bo przy imporcie z innego modułu identyfikator __name__ jest ustawiany na nazwę modułu (pliku).
#19 Metoda „setdefault”
Możesz chcieć ustawiać wartości dla różnych kluczy w słowniku. Na przykład, gdy zliczasz słowa w korpusie. Zwykle robi się to tak:
Tak wygląda to w kodzie:
Bardziej zwięzłym sposobem jest użycie metody setdefault() na obiekcie słownika.
Pierwszy argument metody to klucz, którego szukamy. Drugi argument to wartość, którą ustawimy, jeśli klucza nie ma jeszcze w słowniku — jeśli klucz istnieje, metoda zwróci jego wartość, więc nie zostanie zmieniona.
Triki dotyczące struktury programu
#20 Dopasowanie regex
Wyrażenia regularne pozwalają określać wzorce tekstu do wyszukania; większość osób wie, że można szukać rzeczy skrótem CTRL + F (Windows), ale jeśli nie wiesz dokładnie, czego szukasz, jak to znaleźć? Odpowiedź: szukaj wzorców.
Na przykład numery w UK mają podobny wzorzec: zaczynają się od zera i dziesięciu cyfr lub od +44 zamiast zera i dziesięciu cyfr — drugi wariant to format międzynarodowy.
Regex to ogromna oszczędność czasu. Gdybyśmy mieli zakodować reguły wykrywania przypadków z obrazka zamiast użyć regex, mogłoby to zająć 10+ linii kodu.
Nauka działania wyrażeń regularnych jest ważna nawet, jeśli nie piszesz kodu. Większość nowoczesnych edytorów i procesorów tekstu pozwala używać regexów w funkcjach znajdź i zamień.
#21 Operator „|” w regex
Wyrażenia regularne mają specjalny znak pipe (|), który pozwala dopasować jedno z wielu wyrażeń i można go używać w dowolnym miejscu. To super przydatne przy kilku podobnych wzorcach.
Na przykład „Superman”, „Superwoman” i „Superhuman” mają ten sam prefiks. Możesz więc użyć pipe, by zachować część wzorca, która się powtarza, i zmieniać tę, która ma się różnić. Znowu oszczędzasz cenny czas.
Uważaj na haczyk: jeśli wszystkie wyrażenia, które chcesz dopasować, występują w tym samym tekście, zwrócone zostanie pierwsze dopasowanie — tzn. „An example text containing Superwoman, Superman, Superhuman” zwróci Superwoman.
#22 Parametr „sep” funkcji print()
Liczba programistów Pythona, którzy nie znają pełnych możliwości funkcji print(), jest zaskakująca; jeśli „Hello World” było twoim pierwszym programem, print() zapewne było jedną z pierwszych funkcji wbudowanych, które poznałeś. Używamy print() do wyświetlania sformatowanych komunikatów, ale potrafi ono znacznie więcej.
W powyższym kodzie pokazaliśmy różne sposoby wyświetlenia formatu. Parametr sep to opcjonalny argument funkcji print(), który pozwala określić, jak rozdzielać obiekty, jeśli przekażemy ich więcej niż jeden.
Domyślnie są rozdzielane spacją, ale zmieniliśmy to w naszych wywołaniach — raz ustawiając sep na "", a innym razem na ".".
#23 Funkcje lambda
Funkcje lambda wprowadzają cię na bardziej średnio‑zaawansowany/zaawansowany poziom możliwości Pythona — naucz się Intermediate Python na tym kursie. Na pierwszy rzut oka wyglądają skomplikowanie, ale są dość proste.
W przykładzie użyliśmy jednego argumentu, ale moglibyśmy użyć wielu:
W istocie słowo kluczowe lambda pozwala tworzyć małe, ograniczone, anonimowe funkcje w jednej linii. Zachowują się jak zwykłe funkcje zadeklarowane słowem def, z tą różnicą, że nie mają nazwy.
#24 Metoda „swapcase”
Metoda swapcase() zastosowana do napisu pozwala zamienić wielkie litery na małe i odwrotnie w jednej linii kodu. Zastosowań nie ma wiele, ale warto wiedzieć.
#25 Metoda „isalnum”
Załóżmy, że tworzysz program, w którym użytkownicy podają hasło, a ono musi zawierać kombinację liter i cyfr. Da się to sprawdzić jedną linią, wywołując isalnum() na instancji napisu.
Metoda sprawdza, czy wszystkie znaki są alfanumeryczne (A‑Za‑z, 0‑9). Spacja lub symbol (!#%$&? itd.) zwróci False.
#26 Obsługa wyjątków
Programy w Pythonie kończą działanie, gdy napotkają błąd.
Czasem nie chcemy takiego zachowania, np. gdy z naszym kodem wchodzi w interakcję użytkownik końcowy. Jak źle by było, gdyby program zakończył się przedwcześnie?
Istnieje kilka podejść do przypadków wyjątkowych. Większość programistów Pythona kieruje się zasadą, że łatwiej jest prosić o wybaczenie niż o pozwolenie. Oznacza to, że wolą przechwycić zgłoszony błąd, zapewniając kontekst zdolny do obsłużenia wyjątku. Idea jest taka, że nie ma sensu tracić czasu na zabezpieczanie się przed wszystkimi możliwymi wyjątkami.
Ale to ma sens tylko wtedy, gdy istnieje mechanizm radzenia sobie z problemem po jego wystąpieniu.
#27 Identyfikacja różnic w listach
Oto trzy różne metody porównania różnic między dwiema listami w Pythonie.
Uwaga: O ile nie masz pewności, że list_1 jest podzbiorem list_2, rozwiązanie 1 nie jest równoważne z pozostałymi dwoma.
#28 Args i kwargs
Używamy *args i **kwargs jako parametrów funkcji, gdy nie wiemy, ile zmiennych powinna ona przyjąć.
Parametr *args pozwala przekazać zmienną liczbę argumentów pozycyjnych (tj. bez nazw). Z kolei **kwargs umożliwia przekazanie dowolnej liczby argumentów nazwanych.
W rzeczywistości słowa *args i **kwargs nie są magiczne: magia tkwi w gwiazdkach (*). Moglibyśmy użyć dowolnego słowa po gwiazdkach, ale zwyczaj używania args i kwargs jest powszechny i egzekwowany wśród programistów Pythona.
#29 Wielokropek (Ellipsis)
Ellipsis to obiekt w Pythonie, który można wywołać, wpisując trzy kropki (...) lub wywołując sam obiekt (Ellipsis).
Najbardziej znane zastosowanie to dostęp i wycinki w tablicach wielowymiarowych w NumPy, na przykład:
Inne użycie Ellipsis to placeholder w niezaimplementowanej funkcji.
To znaczy, że możesz użyć Ellipsis, ... lub pass — wszystkie będą poprawne.
#30 Wyrażenia listowe
Nasz ostatni trik to wyrażenia listowe, elegancki sposób tworzenia listy z innej sekwencji. Pozwalają wykonywać złożoną logikę i filtrowanie, jak w powyższym kodzie.
Można to osiągnąć też innymi sposobami; np. moglibyśmy użyć funkcji lambda tak:
Ale wielu Pythonistów uzna to rozwiązanie za mniej czytelne niż wyrażenie listowe.