Mateusz Mazurek – programista z pasją

Python, architektura, ciekawostki ze świata IT

Programowanie Programowanie webowe

Czego nie powinniśmy robić w Pythonie? #1

Programowanie w każdym języku wygląda podobnie. To, co je różni, to detale. Pisząc to słowo mam na myśli pewne rozwiązania, które są dedykowane dla tego jednego, konkretnego języka. Python nie jest tutaj wyjątkiem, natomiast jego elastyczność pozwala tworzyć kod, który jest daleki od ideału. Przy akompaniamencie tego zdania pokażę dziś kilka rozwiązań, które nigdy nie powinny się pojawić w plikach z rozszerzeniem .py.

Porównywanie

Bardzo często widzę instrukcje warunkowe pisane w taki sposób:

1
2
3
4
some_variable = None

if some_variable == None:
    do_something()

Najczęściej piszą je ludzie, którzy już pisali w innym języku i nie bardzo wiedzą, że powinni inaczej. Poprawnie (tj. zgodnie z PEP8) jest używać operatora is:

1
2
3
4
some_variable = None

if some_variable is None:
    do_something()

Podobnie ma się sprawa z porównywaniem zmiennych True/False, tj zamiast porównywania w formie

1
2
3
4
some_variable = False

if some_variable == True:
    do_something()

lub

1
2
3
4
some_variable = False

if some_variable is True:
    do_something()

powinniśmy po prostu zrobić:

1
2
3
4
some_variable = False

if some_variable:
    do_something()

To co tu jest ważne i pojawiło się kilka razy w komentarzach gdzieś na social media to to czym różni się is od ==. Operator „==” sprawdza równość obiektów a operator „is” sprawdza czy to te same obiekty. Ładnie to widać tutaj:

1
2
3
4
5
6
7
8
9
list1 = []
list2 = []
list3 = list1

print(list1 == list2)

print(list1 is list2)

print(list1 is list3)

gdzie output to:

True
False
True

więc to co chciałbym dodać to to że ten punkt dotyczy porównywania z None’em i z True/False – w innych przypadkach efekty stosowania is mogą być różne i warto to wiedzieć.

Iterowanie po słowniku

Gdybym miał dostać złotówkę za każdym razem, kiedy widzę coś takiego jak poniżej, to byłbym bardzo bogatym człowiekiem:

1
2
3
4
d = {"some_key": "some_val", "some_key2":"some_val3"}

for key in d:
    print("{} have value {}".format(key, d[key]))

I nie mam na myśli tu tylko juniorów! Jedynym słusznym zapisem jest:

1
2
3
4
d = {"some_key": "some_val", "some_key2":"some_val3"}

for key, val in d.items():
    print("{} have value {}".format(key, val))

Czekaj, stop!

Podoba Ci się to co tworzę? Jeśli tak to zapraszam Cię do zapisania się na newsletter:
a w ramach prezentu otrzymasz całkowicie za darmo, dwa dokumenty PDF „6 (nie zawsze oczywistych) błędów popełnianych podczas nauki programowania” który jest jednym z efektów ponad siedmioletniej pracy i obserwacji rozwoju niejednego programisty oraz „Wstęp do testowania w Pythonie”, będący wprowadzeniem do biblioteki PyTest.
Jeśli to Cię interesuje to zapraszam również na swoje social media.

Jak i do ewentualnego postawienia mi kawy :)
Postaw mi kawę na buycoffee.to

Uwaga! Poniższe wtrącenie związane z items() / iteritems() jest zasadne tylko dla Pythona 2! W Pythonie 3 funkcja iteritems() nie istnieje, a items() działa używając generatora.

To, o czym powinno się pamiętać to, że funkcja items() nie jest demonem szybkości. Znacznie lepszym rozwiązaniem jest funkcja iteritems() czyli:

1
2
3
4
d = {"some_key": "some_val", "some_key2":"some_val3"}

for key, val in d.iteritems():
    print("{} = {}".format(key, val))

Mimo że różnicy w sposobie użycia nie ma, to pod spodem funkcja items() tworzy nam tuple, co jest dość kosztownym podejściem, natomiast funkcja iteritems() zwraca generator.

Pętla for

Idąc dalej – w pętli for czasem potrzebujemy dostać się do aktualnego indeksu. Potrzeba w wielu przypadkach zasadna, ale wykonanie na pewno nie powinno wyglądać tak:

1
2
3
4
5
elements = ['first', 'second', 'third']

for i in range(len(elements)):
    element = elements[i]
    print(i, element)

jeśli chcemy zrobić to po pythonowemu, użyjmy enumerate():

1
2
3
4
elements = ['first', 'second', 'third']

for i, element in enumerate(elements):
    print(i, element)

To, co warto wiedzieć albo może bardziej, to czego warto być świadomym to działanie funkcji enumerate(). Może po prostu zerknijcie na kod, który mógłby być jej definicją:

1
2
3
4
5
def enumerate(sequence, start=0):
    n = start
    for elem in sequence:
        yield n, elem
        n += 1

Zmierzając do brzegu

Niech ten, kto nigdy nie napisał takiego kodu, pierwszy rzuci kamień…

Tytuł posta ma w sobie „#1” – i poprawnie sugeruje, że artykułów z tej serii będzie więcej. Mam nadzieję, że dzięki temu wpisowi Wasze kody będą coraz lepsze :)

Dzięki za wizytę,
Mateusz Mazurek

A może wolisz nowości na mail?

Subskrybuj
Powiadom o
guest

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.

17 komentarzy
Inline Feedbacks
View all comments
Ja

Wszystko fajnie ale może wyjaśnisz czemu is a nie =?

Michał

Dodatkowo w
if some_variable:
do_something()

będzie spełniony warunek nawet kiedy some_variable != True, np w przypadku gdy sime_variable będzie niepustym stringiem

Robert Krzaczyński

Krótka, rzeczowa i przydatna treść! Ostatnio zaczynam więcej pisać w Pythonie, ze względu na studia i zagłębianie tematyki uczenia maszynowego, dlatego takie artykuły wpasowują się idealnie. Pozdrawiam!

Mateusz Hyla

Przydatny artykuł. Mysle ze przedstawione przyklady poprawnego programowania w Pythonie przekladaja sie glownie na zlozonosc czasowa wykonania sie programu.

Sam zaczynam programowac w Python i na pewno bede sledzil kontynuacje.

Pozdrawiam 🙂.

Łukasz

Aktukuł całkiem fajnie napisany, krótko, zwięźle i na temat. Jednak przyczepie się do dwóch rzeczy. 1. piszesz, że iteritems() jest tylko w Python 2, używasz Pythona 3 i wywołujesz metodę słownika iteritems zamiast items. 2. funkcja range iteruje od 0, wiec nie trzeba podawać pierwszego parametru czyli wystarczy napisać range(len(elements)).

r232n1k

Wiele bym dal, aby nie tylko przeczytac czego nie robic, ale takze DLACZEGO…
pisze to z perspektywy osoby, ktora pythona od 2 miesiecy sie uczy ;)