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:Jeśli to Cię interesuje to zapraszam również na swoje social media.
Jak i do ewentualnego postawienia mi kawy :)
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 :)
Mateusz Mazurek
Wszystko fajnie ale może wyjaśnisz czemu is a nie =?
Operator „==” sprawdza równość obiektów a operator „is” sprawdza czy to te same obiekty. Ładnie to widać tutaj:
list1 = []
list2 = []
list3 = list1
if (list1 == list2):
print(„True”)
else:
print(„False”)
if (list1 is list2):
print(„True”)
else:
print(„False”)
if (list1 is list3):
print(„True”)
else:
print(„False”)
I to zwróci:
True
False
True
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
Potwierdzam, wartość stringa jak jest rzutowany na bool’a jest zależna od jego długości i jak ma długość zero to jest False:)
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!
Dzięki ogromne za miły komentarz!
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 🙂.
Cieszę się że doceniasz, dzięki!
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)).
Cześć! Dzięki za pozytywny komentarz:) co do 1 pkt to kod pod „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.” jest w Pythonie 2, w Pythonie 3 nie uruchomiłby się (brak iteritems().
Punkt 2 – poprawiłem:)
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 ;)
Cześć, dzięki za komentarz. Tam gdzie jest to koniecznie wskazuje powód np. opisuję prędkość lub wskazuje plusy rozwiązania a jeśli brak to jest to po prostu wygodniejsze i/lub bardziej Python’owe rozwiązanie:)