Python zjada dinozaury

Logo pythona

Od jakiegoś czasu uczę się programować w Pythonie z wykorzystaniem Django. Pierwsze wrażenia – oszałamiające. Do tej pory programując w wielu językach, wiedziałem, że jest coś z nimi nie tak, ale nie wiedziałem dokładnie co. Teraz już wiem!

Myślę, że tysiące studentów ucząc się nowego języka zadawało setki razy pytanie: „dlaczego autor nie zrobił tego tak aby MI było wygodnie”?

Ucząc się kolejnych języków miewałem często wrażenie, że: „ten język widział jeszcze dinozaury” (Pascal, C++) lub „ten język napisał pewnie jakiś student na pracę zaliczeniową” (PHP), albo też „ten język ma dobrych kolegów, którzy widzieli dinozaury” (Java).

Problem tak naprawdę polega na tym, że języki te nie były projektowane tak by być wygodnymi dla programistów, tylko z jakichś innych pobudek. Z tego powodu mają w sobie mnóstwo elementów, które są niewygodne i po prostu nie chce się z nich korzystać.

Myślę, że tysiące studentów ucząc się nowego języka zadawało setki razy pytanie: „dlaczego autor nie zrobił tego tak aby MI było wygodnie”? Pytanie to jest bardzo ważne, bo w końcu język programowania jest dla programisty. Nikogo innego nie obchodzi. Maszyna jest w stanie sparsować prawie wszystko, a manager nie czyta kodu.

Niestety bardzo wiele języków nie powstało z myślą o programistach.

Czas na Pythona!

Pythona wyróżnia to, że czujesz, że język ten został stworzony z myślą o Tobie – programiście.

Po Pythona sięgam tak naprawdę po raz drugi. Pierwszy raz bawiłem się nim w gimnazjum. Było to jednak na tyle niezobowiązujące i krótkie, że zdążyłem ten język niemal kompletnie zapomnieć. Teraz więc odkrywam go na nowo.

To co w Pythonie zadziwia na początku to, że jest super-łatwy do czytania. Patrząc na jego kod praktycznie od razu wiesz co się gdzie dzieje. Python może nie jest jedynym językiem z tą właściwością, jednak pozytywnie wyróżnia się pod tym względem. Wystarczy rzucić okiem na jakiś prosty kod:

a = 2
print a
b = a * 3
print b
x = ['ala', 'ma', 'kota']
x = x[0:2]
for y in x:
	print y
def foo(a):
	return a * a
print foo(2)

Poza tym, że Python jest łatwy do nauki i prosty w czytaniu, jest również dobrze zaprojektowany (dobry podział na moduły, duża biblioteka standardowa), elastyczny (rachunek lambda, możliwość modyfikowania typów w locie), szybki (kompilowany) , przenośny (kompiluje się do kodu pośredniego tak jak Java).

Pythona wyróżnia to, że czujesz, że język ten został stworzony z myślą o Tobie – programiście.

Czas na prawdziwy hit!

W Pythonie piszę się większość rzeczy bardzo krótko i zwięźle. Jest to zaleta, którą powinni docenić zarówno programiści, jak i managerowie.

Niemal wszystkie języki mają rozliczne zalety. Dlaczego więc Python? Odpowiedź banalna: mimo bardzo prostej i mało rozbudowanej składni w Pythonie piszę się większość rzeczy bardzo krótko i zwięźle. Jest to zaleta, którą powinni docenić zarówno programiści, jak i managerowie.

Posłużę się przykładem, który jest bardzo frustrujący dla wielu programistów – gettery i settery. Oto przykładowe kody w PHP i Pythonie, które robią to samo:

bar;
	}
	public function setBar($value) {
		$this->bar = $value;
	}
}
?>

to samo w Pythonie:

class Foo:
    def __init__(self):
        self.bar = 0

(sic! To nie jest pomyłka. W Pythonie piszesz gettery i settery dopiero gdy faktycznie są potrzebne i nic przez to nie tracisz!)

Różnica niebanalna prawda? Patrząc na coś takiego trudno się nie oprzeć wrażaniu, że PHP nie zostało zaprojektowane z myślą o programistach. Nie przypomina mi sie żaden inny język programowania, który miałby porządnie rozwiązaną kwestię getterów i setterów.

Podsumowując

Jesteś programistą? Spróbuj Pythona, poczujesz różnicę. Jesteś managerem? Poproś swoich programistów by opowiedzieli Ci o Pythonie. Zainteresujesz ich w ten sposób tematem i w przypływie dobrego humoru sami się go nauczą, a ty oszczędzisz na szkoleniu.

PS. Jeśli znasz inny język, który jest tak samo przyjazny jak Python, czekam na komentarz.

Wracam do Pythona. Mam nadzieje, że w przyszłości Python wywrze na mnie jeszcze większe wrażenie.

  1. lqc pisze:

    Kilka błędów:
    * średnik zamiast „:” -> „def foo(a);”
    * przykład #2 wcale nie definiuję pola „bar” w elementach klady Foo, tylko atrybut samej klasy

    Co rozumiesz przez „elastyczny (rachunek lambda” ? Czy wiesz co to jest rachunek lambda, czy też raczej chodziło ci o to, że są tzw. „lambda wyrażenia”.

  2. cztery pisze:

    Odpowiednikiem tej Pythonowej klasy w PHP powinnno być:
    class Foo
    {
    public $bar = 0;
    }
    Settery i gettery w obu przypadkach to nie są wymagane przez język (nie pisałeś setterów i getterów w pythonie – wyglądają prawie tak samo brzydko, no może z wyjątkiem xproperty )?
    Jeśli chodzi o programowanie to jeszcze sporo przed Tobą zanim powinieneś pisać takie artykuły ;)
    Mnie do Pythona nie przekonałeś, a jako byłego phpowca zabiłeś mnie swoją ignorancją ;)

  3. Tomasz Wysocki pisze:

    lqc:
    Dzięki za uwagi. Jeśli chodzi o „rachunek lambda” miałem na myśli to, że można podobnie jak w językach funkcyjnych operować na funkcjach, jak na zwykłych obiektach. Faktycznie trochę niefortunnie to ująłem.

    cztery:
    Co z tego, że nie są wymagane, jeśli osoby programujące obiektowo i tak muszą je pisać? Magiczne funkcje set i get z PHP są rzadko wykorzystywane, dlatego jesteś skazany na pisanie accesorów lub na brak kontroli dostępu do zmiennych. W Pythonie masz użyteczne narzędzia do tego by pisać settery dopiero wtedy, gdy faktycznie są potrzebne.
    Gdy próbujesz kogoś oceniać, identyfikuj się adresem do strony/bloga, tak by można było sprawdzić jakim autorytetem jesteś w danej dziedzinie. Ocenianie kogoś jako anonim to tylko niepotrzebne marnowanie czasu swojego i innych, gdyż taka ocena nie ma wartości.

  4. hipertracker pisze:

    PHP może i jest syfiasty, ale posiada też przezroczyste akcesory (hint: metody __get() i __set()). A poza tym, to od Pythona dużo ładniejszy jest Ruby. :P

  5. Tomasz Wysocki pisze:

    Znam __get i __set. Jednak możliwość techniczna to jedno, a łatwość i powszechność wykorzystania to drugie. __get i __set wydają się być stworzone raczej dla autorów bibliotek, niż dla zwykłych programistów.
    Jeśli chodzi o Python v Ruby, to chyba wypadają podobnie pod względem wygody. Ja póki co skłaniam się ku Pythonowi. Być może kiedyś zmienią mi się upodobania i przejdę na Ruby.

  6. hipertracker pisze:

    PHP jak i Python obsługują przezroczyste akcesory. Podany przez ciebie przykład akcesorów dla PHP jest bez sensu, bo tak to można i dla Pythona napisać. Poza tym Python ma całkiem sporo takich „magicznych”, brzydko ponazywanych metod. W ogóle metaprogramowanie w Pythonie (choć o niebo lepsze od tego co można w PHP), jest dużo gorsze, brzydsze, mniej wygodne od Ruby. Np. Python to dziś nie ma porządnych funkcji anonimowych. PHP (od wersji 5.3), nie mówiąc o JavaScripcie i Ruby to bez problemu obsługują.

  7. Tomasz Wysocki pisze:

    Ideą tego przykładu nie było pokazanie, że PHP jest kiepskie, tylko „standardowego” podejścia do dostępu do zmiennych. Być może lepiej by było gdybym zmienił język przykładu na Javę, ale nie o to tu chodzi. Chodzi o to, że w Pythonie rzeczy najczęściej używane pisze się po prostu krótko. A to powinno być podstawą wszystkich języków.

  8. hipertracker pisze:

    To nie jest nawet standardowe podejście, takie „javowe” akcesory w PHP piszą tylko jacyś lamerzy. A i krótki zapis to nie wszystko (Perl jest też krótki i co z tego?) Ważniejsze są inne rzeczy. Choćby pełna obiektowość Ruby, Pythona, Scali której nie ma ani w Javie ani w PHP. Funkcje które są obiektami pierwszego rzędu itp. itd.

  9. Zdaję sobie sprawę z tego, że przyzwyczajenie to nie jest dobra rzecz, ale moim zdaniem jest jakiś powód [inny niż lenistwo twórców], dla którego tyle współcześnie używanych języków zapożyczyło składnię z C / C++. Nie wiem, jak Wy, ale ja nie widzę specjalnego zysku w zastąpieniu np. słowa kluczowego „function” skróconą formą „def”, tym bardziej, że we współczesnych IDE wpisanie obu sprowadza się do wpisania dwóch pierwszych liter i zatwierdzenia [Enter]em jednej z podpowiedzianych pozycji. Na pewno trudno byłoby mi się także przestawić na sposób pisania kodu bez używania jakichkolwiek nawiasów klamrowych, ponieważ poprawiały one znacznie czytelność kodu, umożliwiając pisanie „na swój sposób”. Rozumiem, że kod ma być czytelny, ale zmuszanie programisty do pisania w stylu „jedna instrukcja w linijce” to nie jest droga do osiągnięcia celu. Porównanie pisania akcesorów PHP vs Python też jest nie do końca szczęśliwe, ponieważ IDE zwykle je generuje, więc nikt palców nie męczy [ja akurat piszę sam, ale to już prywatne podejście do sprawy], po drugie nie lubię korzystać z funkcjonalności udostępnianych tylko przez jeden język, tak więc w większości wszystkie magiczne __something() odpadają.

    Podsumowując – w żadnym wypadku nie zamierzam krytykować autora za ten wpis, bo Python dobrym językiem / środowiskiem jest i basta, ale czy miałbym się na niego przesiąść? Trudno powiedzieć, na razie nie muszę, więc zostaję przy swoim.

  10. @hipertracker: dlaczego uważasz np. taki getter który zwraca wyłącznie wartość atrybutu za lamerski? Wszystko zależy od przeznaczenia takiej metody, moim zdaniem nie powinieneś obrażać ludzi za ich decyzje, jeśli nie są jednoznacznie złe. Jeśli masz w klasie atrybut, załóżmy jakiś string przechowujący nazwę użytkownika, to co masz zrobić poza [PHP] „return $this->username;”? W setterach wiadomo, trzeba sprawdzić, co zostało podane, czy jest poprawne, itp., itd. i dopiero wtedy podstawić, ale w getterach „zwykły akcesor” jest w większości przypadków wystarczający.

  11. hipertracker pisze:

    Lamerskie to jest pisanie w stylu getDupa/setDupa w języku, który posiada przezroczyste akcesory. Problem z javowymi akcesorami jest poważniejszy i żadne IDE tego nie rozwiąże: http://tinyurl.com/yhdp8df

  12. Lamerskie to jest po pierwsze nazywanie wszystkich wokół lamerami, bo mają czelność uważać inaczej niż Jaśnie Pan, to tak tytułem wstępu.

    Przezroczyste akcesory nie załatwiają sprawy, ponieważ w takim wypadku odwołujesz się bezpośrednio do atrybutu, któremu też być może będziesz chciał zmienić nazwę. I co wtedy? Zrobisz sobie w __get() i __set() ifa, że jak chcę „dupa”, to daj mi „niedupa”? Jestem przeciwny pisaniu niepotrzebnego i nieużywanego kodu, ale zawsze używam jawnych akcesorów [nie ma akcesora == nie ma dostępu] dla atrybutów klas, ponieważ mają one czytelne nazwy i są poniekąd standardem, więc nikt się nie zastanawia co dana metoda robi, a ukrywając dostęp za metodą można dowolnie żonglować tym, co jest „pod maską”.

    Po drugie pastwicie się nad tymi getsetami, jakby naprawdę było się o co kłócić. Nie wiem jak u was, ale np. jak mam klasę CPerson, która ma atrybut surname, to u mnie getter wygląda następująco: return $this->surname;. W setterze dorzucam gratis parę testów, czy ktoś mi nie podstawia jakiegoś inta za nazwisko, ale nic poza tym. Może wasze akcesory liczą jakieś zaawansowane całki, czy sterują w międzyczasie rakietami ziemia – ziemia, nie wiem, moje niestety robią tylko to, co w nazwie. Generalnie, jeśli akcesor ma robić coś więcej [istotnie więcej] niż to, co w nazwie, to awansuje do rangi metody, a tam już „hulaj dusza”.

    Pozdrawiam i mam nadzieję, że się nikt na mnie nie obraził. Rzeczowa dyskusja FTW! ;]

  1. There are no trackbacks for this post yet.

Leave a Reply