Jak vám Zen of Python může pomoci napsat lepší kód

Chcete se zdokonalit v psaní kódu Python? Zde je návod, jak vám Zen of Python může pomoci udělat první kroky k tomu.

Python se velmi snadno učí. Ale psaní idiomatického a Pythonic kódu, který se snadno udržuje, může být náročné – zvláště pro začínající programátory. PEP-20 představil „The Zen of Python“, báseň Tima Peterse, která nastiňuje důležitost psaní Pythonic kódu, který se drží osvědčených postupů.

Chcete-li si přečíst Zen of Python, můžete spustit Python REPL a spustit:

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Jak je vidět, většina aforismů v zenu Pythonu je samovysvětlující. Některé aforismy by měly být při interpretaci spojeny s dalšími, zatímco jiné jsou v rozporu s dřívějším aforismem. Nicméně Zen of Python je zábavné, poutavé a praktické čtení!

Výklad zenu Pythonu

Zen of Python byl navržen tak, aby měl 20 hlavních principů pro programování v Pythonu. Zatím však existuje pouze 19 aforismů. Pojďme si je projít.

  Jak zapnout režim jízdy Samsung Galaxy S3

Krásná je lepší než ošklivá.

Tento aforismus zdůrazňuje důležitost psaní elegantního a Pythonic kódu.

Následující fragment kódu má vůni kódu:

def square(num):
    squares = []
    for i in range(num):
        squares.append(i*i)
    return squares

Funkce:

  • Inicializuje prázdný seznam
  • Má smyčku uvnitř funkce, která připojuje prvky na konec seznamu a
  • Nakonec vrátí seznam

I když je to funkčně správné – není to Pythonic – a je těžké to udržovat.

Můžete to napsat mnohem elegantněji pomocí generátorů. Zde je funkce generátoru ekvivalentní výše uvedené funkci:

def square(num):
    for i in range(num):
        yield i*i

Nebo ještě lépe, můžete mít následující výraz porozumění generátoru:

num = ...
squares = (i*i for i in range(num))

Explicitní je lepší než implicitní.

Při psaní kódu nenechávejte ostatní vývojáře a uživatele hádat implikované nebo výchozí chování kódu. Buďte explicitní. Vezměte si příklad importu zástupných znaků:

from some_module import * # wildcard import
from some_other_module import *

result = some_function() # where did this come from?

Vyhněte se co nejvíce použití importu zástupných znaků. Protože to není jednoznačné a neefektivní. Při importu funkcí a tříd z jiných modulů buďte konkrétní:

from some_module import this_function # explicit import

result = this_function() # we now know.

Jednoduché je lepší než složité.

Tento aforismus říká, že bychom měli kód udržovat jednoduchý a vyhnout se zbytečné složitosti. Například: možná budete chtít obrátit řetězec a implementujete následující rekurzivní řešení:

def reverse_string(my_string):
  if my_string == "":
    return my_string
  else:
    return reverse_string(my_string[1:]) + my_string[:1]

I když to funguje, je to pravděpodobně přetechnizované řešení tohoto problému – vzhledem k tomu, že existují jednodušší a pythoničtější způsoby, jak to udělat.

Zde je postup krájení řetězce:

>>> rev_string = my_string[::-1]
>>> rev_string
'nohtyP'

A zde je přístup využívající vestavěné metody a funkce:

>>> rev_string = ''.join(reversed(my_string))
>>> rev_string
'nohtyP'

Komplexní je lepší než komplikovaný.

Co tedy tento další aforismus v Zen of Python sděluje?

Obrácení řetězce v Pythonu je super jednoduchá operace. V praxi však možná potřebujeme složitější logiku. Zde je poměrně jednoduchý příklad:

Řekněme, že se potřebujete připojit k databázi:

  • Nejprve byste měli analyzovat konfigurační soubor toml – abyste získali konfigurační informace databáze.
  • Měl by být nainstalován konektor databáze.
  • Poté můžete definovat funkci pro připojení k databázi, předvídat chyby připojení, implementovat zpracování chyb a mnoho dalšího.
  • Nakonec, po připojení k databázi, ji můžete dotazovat.

I když je to stále dostatečně jednoduché, vyžaduje to složitější logiku ve srovnání s obrácením řetězce. To ale neznamená, že to musí být složité. Stále můžete efektivně využívat funkce kódu vestavěných modulů a organizovat svůj kód tak, aby jej ostatní vývojáři mohli číst, rozumět mu a přispívat k němu.

Ploché je lepší než vnořené.

Plochou strukturu lze snadno analyzovat a pochopit než vnořenou strukturu. Při práci na projektu můžete být v pokušení izolovat funkčnost vytvořením samostatných modulů. Příliš velká granularita však může být nadměrná.

  Jak přidat podpis do dokumentu aplikace Word?

To znamená, že často budete muset jít za plochou strukturu. Ale i když potřebujete hnízdění, omezte ho na minimum.

Zde je příklad:

from db_info.config.actions.parse.parse_config import parse_toml # too difficult to parse!
...

from db_config.parse_config import parse_toml # much better!
...

Řídké je lepší než husté.

Pokud na své vývojářské cestě teprve začínáte, můžete být v pokušení nadužívat některé funkce jazyka. Například porozumění seznamu jsou Pythonic – ale pouze tehdy, když je použijete tam, kde jsou potřeba.

Podívejte se na následující porozumění:

prices_dict = {'melons':40,'apples':70,'berries':55}
items = [(fruit,price) for fruit in prices_dict.keys() if fruit.startswith('m') for price in prices_dict.values() if price < 50]
print(items)
# Output: [('melons', 40)]

Porozumění seznamu je příliš husté a obtížně se analyzuje. V tomto případě bude použití ekvivalentu cyklu for s podmíněnými podmínkami čitelnější. Význam porozumění je obtížné pochopit. 🙂

Čitelnost se počítá.

Vždy byste měli psát čitelný kód. Zde je několik jednoduchých způsobů, jak zlepšit čitelnost kódu:

  • Použití popisných názvů proměnných
  • Přidání dokumentačních řetězců pro funkce a třídy
  • Komentující kód tam, kde je potřeba
  • Přidání tipů pro argumenty a návratové typy funkcí

Speciální případy nejsou natolik zvláštní, aby porušovaly pravidla.

Měli byste – co nejvíce – dodržovat pravidla jazyka a doporučené osvědčené postupy.

Ale je to vždy možné? Ne, a proto tu máme další aforismus.

I když praktičnost poráží čistotu.

Toto je pokračování předchozího aforismu. I když se doporučuje dodržovat pravidla jazyka, v určitých případech je naprosto v pořádku některé zásady nedodržovat.

Chyby by nikdy neměly projít tiše.

V Pythonu jsou chyby za běhu docela běžné. Je dobrým zvykem, že byste měli chyby vždy řešit a neumlčovat je jako rychlou opravu.

Můžete předvídat a implementovat vhodné zpracování chyb – pro různé typy chyb:

try:  
    # doing this
except ErrorType1:
    # do something
except ErrorType2:
    # do something else
...

Měli byste se vyvarovat holých a obecných výjimek. Novější verze Pythonu (od Pythonu 3.11) podporují řetězení výjimek a skupiny výjimek, aby mohly provádět sofistikovanější zpracování výjimek.

Pokud není výslovně umlčen.

To navazuje na předchozí aforismus. Pokud návrh vyžaduje nebo umožňuje umlčení chyby, mělo by to být provedeno explicitně.

Například: při připojování k databázi můžete narazit na OperationalError kvůli neplatným konfiguračním informacím. Zkuste se připojit pomocí vlastní konfigurace. V případě, že dojde k chybě OperationalError, použijte výchozí konfiguraci a zkuste se připojit k databázi.

try:
   # connecting using custom config
except OperationalError:
   # connect using default config

Tváří v tvář nejasnostem odmítněte pokušení hádat.

Tento aforismus v zenu Pythonu je samovysvětlující. Jste-li na pochybách, nehádejte. Ale spusťte kód a zkontrolujte výstup. Poté v závislosti na tom, zda máte požadované chování, vylepšete čitelnost nebo upravte logiku podle potřeby.

  Jak vytvořit vlastní klávesové zkratky pro jakoukoli aplikaci Mac

Vezměte si následující jednoduchý příklad s n-ticí Booleanů:

>>> True, True == (True, True)
(True, False)
>>> True, (True == (True, True))
(True, False)
>>> (True, True) == (True, True)
True

Měl by existovat jeden – a nejlépe pouze jeden – zřejmý způsob, jak to udělat.

Ke splnění určitého úkolu by měl existovat pouze jeden doporučený pythonic způsob, jak to provést. Pro jakýkoli problém však můžeme mít několik řešení.

I v jednoduchém příkladu obrácení řetězce jsme se podívali na rekurzivní řešení, krájení řetězců a metodu join().

To je také vnitřní vtip vzhledem k nekonzistentnímu používání em-pomlček. Obecně používáme em-pomlčky bez úvodních a koncových mezer. Nebo jej použijeme s počáteční i koncovou mezerou.

Takže zde je to, co můžeme usuzovat. Aforismus, který zdůrazňuje, že by měl existovat jeden – a pouze jeden – Pythonic způsob, jak dělat věci, může být napsán více než dvěma způsoby.

I když to nemusí být zpočátku zřejmé, pokud nejste Holanďané.

Napsáno lehce, odkazuje to na Guida Van Rossuma, tvůrce Pythonu (který je Holanďan). (Nej)pythonický způsob, jak splnit konkrétní úkol, je přirozený pouze pro tvůrce Pythonu.

Pro vývojáře to tedy vyžaduje zkušenosti – a učení se ze zkušeností – aby se lépe naučili využívat funkce jazyka.

Teď je to lepší než nikdy.

Stejně jako u několika dalších aforismů v Zen of Python, i tento lze interpretovat několika různými způsoby.

Jedním z výkladů je, že jako vývojář je docela běžné otálet se zahájením kódování projektu. Spíše než čekat na plánování nejjemnějších detailů projektu je lepší nápad začít hned.

Další možný výklad je: kód, který běží v konečném počtu kroků – a končí – je často lepší než kód, který je zabugovaný a uvízne v nekonečné smyčce.

I když nikdy není často lepší než právě teď.

Zdá se, že tento aforismus je v rozporu s předchozím. I když je lepší neotálet, měli bychom problém stále promyslet a podle toho navrhnout kód.

Kódování modulu – aniž byste tomu věnovali náležitou pozornost – s pachem kódu a anti-vzory je špatný nápad. Protože takový kód je obtížné refaktorovat a implementovat nápravná opatření.

Pokud se implementace těžko vysvětluje, je to špatný nápad.

Jakákoli logika – jakkoli může být složitá – může být vždy implementována ve formě, která se dá jednoduše vysvětlit a snadno pochopit.

Pokud je implementace obtížně vysvětlitelná, pravděpodobně je to zbytečná složitost. Kód lze upravit nebo předělat, aby bylo snazší jej sledovat.

Pokud je implementace snadno vysvětlitelná, může to být dobrý nápad.

To souvisí s předchozím aforismem a je také samovysvětlující. Pokud lze implementaci vysvětlit jednoduše, pak je to pravděpodobně dobrý nápad.

Protože takový kód, jehož implementaci lze popsat – jednoduše řečeno – bude velmi pravděpodobně čitelný a snadno sledovatelný – s minimální složitostí.

Jmenné prostory jsou skvělý nápad – pojďme jich udělat víc!

V Pythonu lze k objektům v určitém rozsahu přistupovat pomocí jejich jmen v jejich jmenném prostoru. Můžete například vytvořit třídu a použít ji jako šablonu k vytvoření instancí třídy. Nyní budou všechny proměnné instance ve jmenném prostoru instance.

To nám umožňuje používat objekty se stejným názvem – bez konfliktů – tak, jak jsou v různých jmenných prostorech. Měli byste je však používat pouze podle potřeby a zajistit, aby nebyla ohrožena jednoduchost a čitelnost kódu.

Závěr

To je pro tento tutoriál vše! Doufám, že vám tato příručka pomohla pochopit, jak Zen of Python zdůrazňuje styl kódu a správné postupy kódování v Pythonu. Čím více kódujete, tím lépe se k tomu dostanete.

Pokud se chcete naučit psát stručný a čitelný kód, přečtěte si tento článek o jednotných linkách Pythonu.