Hur Zen of Python kan hjälpa dig att skriva bättre kod

By rik

Förbättra Din Python-Kod med Zen of Python

Är du redo att ta dina Python-färdigheter till nästa nivå? ”The Zen of Python” kan ge dig de riktlinjer du behöver för att utvecklas.

Python är känt för sin användarvänlighet, men att skapa kod som är lätt att underhålla och följer de bästa Python-konventionerna kan vara en utmaning, särskilt för nybörjare. Genom PEP-20 introducerades ”The Zen of Python”, en dikt av Tim Peters, som understryker betydelsen av att skriva kod som följer etablerade normer.

För att utforska ”The Zen of Python”, starta en Python REPL (Read-Eval-Print Loop) och skriv följande kommando:

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

Vackert är bättre än fult.
Explicit är bättre än implicit.
Enkelt är bättre än komplext.
Komplext är bättre än komplicerat.
Platt är bättre än kapslat.
Gles är bättre än tät.
Läsbarhet är viktigt.
Speciella fall är inte tillräckligt speciella för att bryta mot reglerna.
Även om det praktiska slår renhet.
Fel bör aldrig passera tyst.
Om det inte uttryckligen tystas.
Inför tvetydighet, vägra frestelsen att gissa.
Det borde finnas ett – och helst bara ett – självklart sätt att göra det på.
Även om det sättet kanske inte är självklart till en början om du inte är holländare.
Nu är bättre än aldrig.
Även om aldrig ofta är bättre än *just* nu.
Om implementeringen är svår att förklara är det en dålig idé.
Om implementeringen är lätt att förklara kan det vara en bra idé.
Namnutrymmen är en fantastisk idé – låt oss göra fler av dem!

De flesta av ”The Zen of Pythons” aforismer är intuitiva, medan andra kan behöva tolkas i samband med varandra. Vissa kan till och med verka motstridiga. Trots detta är ”The Zen of Python” en stimulerande och praktisk läsning för alla Python-utvecklare.

Tolkning av Zen of Python

Det sägs att ”The Zen of Python” ursprungligen skulle innehålla 20 vägledande principer, men för tillfället finns det 19. Låt oss utforska dem närmare.

Vackert är bättre än fult

Denna aforism betonar vikten av att skriva välstrukturerad och elegant kod.

Här är ett exempel på kod som inte följer Python-konventionerna:


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

Denna funktion:

  • Skapar en tom lista.
  • Använder en loop för att lägga till element i listan.
  • Returnerar sedan listan.

Även om funktionen är korrekt, saknar den elegans och är svår att underhålla. Ett mer elegant sätt att skriva samma kod är att använda generatorer. Här är ett exempel:


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

Eller ännu bättre, en generatorförståelse:


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

Explicit är bättre än implicit

När du utvecklar kod, låt inte andra utvecklare eller användare gissa kodens avsedda eller standardbeteende. Var tydlig i dina avsikter. Undvik jokerteckenimporter, som i följande exempel:


from some_module import * # jokerteckenimport
from some_other_module import *

result = some_function() # var kommer denna funktion ifrån?

Jokerteckenimport kan leda till oklarheter och ineffektivitet. Var specifik när du importerar funktioner eller klasser från andra moduler:


from some_module import this_function # explicit import

result = this_function() # nu vet vi var den kommer ifrån

Enkelt är bättre än komplext

Denna princip uppmanar oss att hålla koden enkel och undvika onödig komplexitet. Till exempel, om du vill vända en sträng, kan du implementera följande rekursiva lösning:


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

Även om koden fungerar, är det en överkonstruerad lösning med tanke på att det finns enklare och mer Python-vänliga sätt att göra detta.

Här är ett exempel med strängskärning:


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

Och här är ett exempel med inbyggda metoder:


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

Komplext är bättre än komplicerat

Vad innebär denna aforism?

Att vända en sträng i Python är en enkel operation. Men i verkligheten behöver vi ofta mer komplex logik. Här är ett exempel:

Tänk dig att du ska ansluta till en databas:

  • Först måste du läsa in en konfigurationsfil för att få databasens inställningar.
  • Sedan behöver du etablera en anslutning till databasen.
  • Efter det måste du definiera en funktion för att ansluta till databasen, hantera anslutningsfel, och mycket mer.
  • Slutligen, efter att ha anslutit till databasen, kan du göra en förfrågan.

Även om det fortfarande är enkelt, kräver denna uppgift en mer komplex logik än en strängvändning. Det betyder inte att det behöver vara komplicerat. Du kan fortfarande använda inbyggda moduler och strukturera din kod så att andra kan förstå och bidra till den.

Platt är bättre än kapslad

En platt struktur är enklare att förstå än en kapslad. När du arbetar med ett projekt kan du bli frestad att separera funktionalitet i olika moduler. Men överdriven granularitet kan vara oönskad.

Ofta behöver man gå bortom en platt struktur, men försök att hålla kapslingen till ett minimum. Till exempel:


from db_info.config.actions.parse.parse_config import parse_toml # Svårt att följa!
...

from db_config.parse_config import parse_toml # Mycket bättre!
...

Gles är bättre än tät

Om du är en ny utvecklare kan du frestas att överutnyttja vissa funktioner i språket. Listförståelser är ett exempel på detta. De är användbara, men endast när de används på rätt ställe.

Här är ett exempel på en tät listförståelse:


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)]

Listförståelsen är för tät och svår att förstå. I det här fallet är det mer läsbart att använda en vanlig loop med villkor. Det är med andra ord svårt att följa listförståelsen. 🙂

Läsbarheten räknas

Du bör alltid sträva efter att skriva lättläst kod. Här är några tips för att förbättra läsbarheten:

  • Använd beskrivande variabelnamn.
  • Lägg till docstrings för funktioner och klasser.
  • Kommentera koden där det behövs.
  • Använd typ-hints för funktionsargument och returvärden.

Särskilda fall är inte tillräckligt speciella för att bryta mot reglerna

Du bör följa språkets regler och rekommendationer så mycket som möjligt.

Men är detta alltid möjligt? Nej, och det är därför vi har nästa aforism.

Även om det praktiska slår renhet

Detta är en fortsättning på den tidigare aforismen. Även om det är rekommenderat att följa reglerna, är det i vissa fall okej att avvika från dem.

Fel får aldrig passera tyst

I Python är fel vid körning ganska vanliga. Som en bra vana bör du alltid hantera fel istället för att ignorera dem.

Du kan förutse och implementera lämplig felhantering för olika feltyper:


try:
    # gör något
except ErrorType1:
    # hantera fel 1
except ErrorType2:
    # hantera fel 2
...

Du bör undvika att använda generiska undantag. Nyare versioner av Python (från och med 3.11) har stöd för undantagskedjor och undantagsgrupper för mer sofistikerad felhantering.

Om det inte uttryckligen tystats

Detta är en fortsättning på den tidigare aforismen. Om koden kräver att fel tystas, ska detta göras explicit.

Till exempel: när du ansluter till en databas kan du stöta på `OperationalError` på grund av felaktig konfigurationsinformation. Försök att ansluta med en anpassad konfiguration. Om det uppstår ett fel, använd standardkonfigurationen och försök ansluta igen.


try:
   # anslut med anpassad konfiguration
except OperationalError:
   # anslut med standardkonfiguration

Inför tvetydighet, vägra frestelsen att gissa

Denna aforism i ”The Zen of Python” är tydlig. När du är osäker, gissa inte. Kör koden och kontrollera resultatet. Beroende på om koden beter sig som förväntat, förbättra läsbarheten eller justera logiken efter behov.

Här är ett exempel med en tuple av booleans:


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

Det borde finnas ett – och helst bara ett – självklart sätt att göra det på

För en given uppgift bör det finnas ett och endast ett rekommenderat sätt att lösa det på. Men för många problem kan det finnas flera lösningar.

Till exempel tittade vi på en rekursiv lösning, strängskärning och metoden `join()` för att vända en sträng.

Detta är också ett internt skämt med tanke på den inkonsekventa användningen av em-streck. Vanligtvis används em-streck utan mellanslag. Men det går också att använda em-streck med mellanslag.

Slutsatsen är att aforismen om att det ska finnas ett, och endast ett Python-sätt att göra saker på, i sig själv kan formuleras på mer än två sätt.

Även om det sättet kanske inte är självklart till en början om du inte är holländare

Detta är en skämtsam referens till Guido van Rossum, skaparen av Python, som är holländare. Det (ofta) ”Pythoniska” sättet att göra något är intuitivt för skaparen av Python.

För utvecklare krävs det erfarenhet och lärande för att bli bättre på att utnyttja språkets funktioner.

Nu är bättre än aldrig

Precis som med andra aforismer i ”The Zen of Python”, kan denna aforism tolkas på flera sätt.

En tolkning är att utvecklare ofta skjuter upp att börja koda. Istället för att vänta med att planera ut varenda detalj i ett projekt, är det bättre att börja nu.

En annan tolkning är att kod som körs i ett ändligt antal steg och avslutas är oftast bättre än kod som har buggar och hamnar i en oändlig loop.

Även om aldrig ofta är bättre än just nu

Denna aforism verkar motsäga den föregående. Även om det är bra att inte skjuta upp saker, bör du tänka igenom problemet ordentligt innan du börjar koda.

Det är en dålig idé att börja skriva kod utan att tänka ordentligt på saken, eftersom det kan leda till kod som är svår att refaktorisera och fixa.

Om implementeringen är svår att förklara är det en dålig idé

Oavsett hur komplex en logik är, kan den alltid implementeras på ett sätt som är lätt att förklara och förstå.

Om en implementering är svår att förklara, finns det troligtvis en onödig komplexitet. Koden kan behöva modifieras eller refaktoriseras för att underlätta förståelsen.

Om implementeringen är lätt att förklara kan det vara en bra idé

Denna aforism hänger ihop med den tidigare, och är också självförklarande. Om en implementering kan förklaras på ett enkelt sätt är det troligtvis en bra idé.

Kod vars implementering är lätt att förklara är mer trolig att vara lättläst och enkel att förstå, med minimal komplexitet.

Namnutrymmen är en tutande bra idé – låt oss göra fler av dem!

I Python kan objekt i ett specifikt omfång nås med sina namn i ett namnutrymme. Du kan till exempel skapa en klass och använda den som en mall för att skapa instanser av klassen. Alla instansvariabler kommer nu att vara inom instansens namnutrymme.

Detta gör att du kan använda objekt med samma namn, utan konflikter, eftersom de finns i olika namnutrymmen. Men du bör endast använda dem när de behövs och se till att det inte påverkar kodens enkelhet och läsbarhet negativt.

Slutsats

Det var allt för den här genomgången! Jag hoppas att den här guiden har gett dig en djupare förståelse för hur ”The Zen of Python” betonar vikten av kodstil och bra programmeringsmetoder i Python. Ju mer du kodar, desto bättre blir du.

Om du är intresserad av att lära dig hur man skriver kortfattad och läsbar kod, kan du utforska den här artikeln om Python one-liners.