Dziś napiszę dla odmiany coś o Pythonie. Nie porzucam rzeczywistości rozszerzonej, HoloLens i Unity, które obecnie nadal pozostają tematem wiodącym. Przyszedł mi do głowy natomiast taki mini-cykl związany z Pythonem i pewnymi rzeczami naokoło niego, który wprowadzi pewne urozmaicenie, a jednocześnie będzie w zgodzie z regułami DSP 2017.
Czemu w ogóle warto uczyć się Pythona? Python jest językiem uniwersalnego zastosowania o popularności niewiele ustępującej C# i jest często używany obok języka R w uczeniu maszynowym i Data Science (w aplikacjach serwerowych i webowych też, ale nie jest to już takie wyjątkowe). Jest też głównym językiem używanym do programowania Raspberry Pi (jak się na nim postawi Windows 10 IoT Core to można pisać i w C#, co też zrobiłem w zeszłym roku i wcześniej, ale mówię jak jest generalnie). Visual Studio 2017 i 2015 oferuje wsparcie w postaci Python Tools, a ostatnio Python stał się językiem natywnie wspieranym przez SQL Server 2017, który przy wsparciu dla procesorów graficznych przeobraża się w wydajną platformę do budowania aplikacji AI.
Do początkowych zabaw z językiem może wystarczyć nam nawet sama przeglądarka internetowa jeśli wybierzemy środowisko Jupyter. Myślę, że wpis Nadal w kosmicznym klimacie – Jupyter krótko i treściwie wprowadza w używanie tego narzędzia. Jupitera możemy postawić także u siebie i również wtedy korzystać z przeglądarki internetowej, co też uczyniłem z uwagi na rozłączanie wersji on-line po okresie bezczynności. Instalujemy wtedy najpierw popularne środowisko Anaconda, które znacząco ułatwia zarządzanie pakietami i instalacjami Pythona.
A teraz trochę uwag odnośnie poznawania podstaw Pythona, a także trochę ciekawostek i rzeczy, które nieraz trudno będzie odnaleźć w innych językach.
1# Czystość i porządek
Za pomocą wcięć sterujemy zagnieżdżaniem bloków. Obchodzimy się bez nawiasów.
2# Łatwiejsza matematyka
Pamięta ktoś silnię ze szkoły podstawowej? W standardowej bibliotece math jest do niej funkcja.
Operator potęgi w samym języku
Bajka. Nielimitowana precyzja dla int. Liczby ograniczone jedynie pamięcią maszyny.
Na poziomie języka możemy definiować liczby urojone i zespolone, to nieczęsto się zdarza !
Mało tego, dzięki pakietowi cmath pierwiastek z –1 istnieje jako liczba urojona:
Pakiet cmath pozwala wyliczyć pewne wartości dla liczb zespolonych np. fazę.
Po co nam takie liczby? Może do faktur się nie przydadzą, ale już do obliczeń związanych z elektrycznością jak najbardziej. Dodatkowo przypomina mi się jak w zeszłym roku używałem szybkiej transformaty Fouriera do rozkładu dźwięku na zakresy częstotliwości. Tam też były liczby zespolone, tyle że w Javie czy C# trzeba sobie jakoś samemu je zamodelować.
Float duży zakres i dokładność.
Klasa Decimal w standardowym module decimal.
Wartości niecałkowite należy zawsze podawać w cudzysłowie, inaczej otrzymamy coś takiego:
Ułamki można też definiować za pomocą klasy Fraction ze standardowego modułu fractions.
3# Warunki i pętle
Zamiast if else można krócej, wystarczy elif.
Oprócz for jest też oczywiście pętla while.
4# Kolekcje
string - Unicode, nie ma oddzielnego typu char, po prostu mamy 1-znakowy string
formatowanie napisów (jeden z wielu wariantów):
bytes - reprezentacja bajtowa napisów string, w zapisie przed cudzysłowem piszemy literę b
a teraz zdekodujmy misia:
list - listy
Ujemne indeksy list są możliwe! Indeks ostatniego elementu możemy alternatywnie opatrzyć wartością –1, a indeks każdego elementu przed nim jest o 1 mniejszy. Nie zaleca się tradycyjnego z innych języków wyliczania ostatniego indeksu jako długość listy - 1.
W Pythonie nawet zakres od 1 do –1 ma sens:
Bardzo poręczne są też przedziały otwarte:
A jak skopiować listę? Wystarczy:
Przy okazji widzimy operator is, który w Pythonie sprawdza czy zmienne wskazują na ten sam obiekt. Z kolei operator == dokonuje porównywania zawartości.
Mnożenie listy w Pythonie, zwłaszcza podczas jej inicjowania, ma sens:
Usuwanie elementu o wskazanym indeksie z listy jest nieco dziwne, bo w takim przypadku używamy operatora del:
dict - słowniki
tuple - krotki
Przecinek czasem robi różnicę:
Przy okazji widzimy funkcję type do sprawdzania typu.
Jak zamienić wartości zmiennych w jednej linii?
Szybka zamiana jednych struktur w inne, np. listy krotek w słownik:
range - zakres
Python to przykład języka z zakresami, które mogą kojarzyć się z Objective-C czy Swift.
set - zbiór
Co ciekawe pustego zbioru nie utworzymy za pomocą {}, a jedynie przez konstruktor set.
5# Funkcje
Do ich definiowania używamy słówka def.
Można definiować domyślne wartości dla parametrów podobnie jak choćby w C#.
6# Obiekty
Wszystko jest obiektem (w tym typy prymitywne i funkcje). Każdy obiekt ma swoje id, nawet prosta liczba:
Język jest dynamiczny, ale ściśle typowany. Nie ma niejawnych konwersji typów. Popatrzmy na wcześniej zdefiniowaną funkcję sum. Jak podałem jej teraz 2 stringi, to ich suma wyraziła się w konkatenacji. Pokazuje to siłę języka. Jednak jeśli podam tej funkcji różne typy jak string i int, to automatyczna konwersja nie nastąpi i wystąpi błąd.
Zakresy nazw zmiennych:
- local - wewnątrz bieżącej funkcji
- enclosing - wewnątrz jakiejkolwiek zagnieżdżonej funkcji
- global - na najwyższym poziomie modułu (o modułach przy innej okazji)
- built-in - dostarczana przez moduły wbudowane
O ile poniższy kod nie budzi wątpliwości:
o tyle ten poniżej jest niespodzianką:
Otóż wewnątrz funkcji x zostało potraktowane jako nowa lokalna zmienna. Ale jest sposób by temu zaradzić. Można jawnie powiedzieć, żeby x wewnątrz funkcji było traktowane jako nazwa globalna:
Na ten raz wystarczy. Następnym razem, jeśli będzie to odcinek o Pythonie, to pójdziemy w bardziej zaawansowane konstrukcje języka albo poeksperymentujemy z narzędziami… Stay tuned.