Ønsker du å forbedre dine ferdigheter i Python-programmering? Da er det lurt å se nærmere på hvordan «The Zen of Python» kan guide deg i riktig retning.
Python er kjent for å være et brukervennlig programmeringsspråk, men å skrive kode som er lett å vedlikeholde og følger «Pythonic»-stilen kan være vanskelig, særlig for nybegynnere. «The Zen of Python,» som ble introdusert gjennom PEP-20 og skrevet av Tim Peters, er et dikt som fremhever betydningen av å skrive Python-kode som følger de beste praksisene.
For å lese «The Zen of Python,» kan du enkelt starte en Python REPL og skrive inn:
>>> 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!
De fleste av prinsippene i «The Zen of Python» er ganske selvforklarende, men noen krever litt tolkning og kan til og med virke motstridende. Likevel er «The Zen of Python» en inspirerende og praktisk tekst for enhver Python-programmerer.
Tolkning av «The Zen of Python»
Det var ment at «The Zen of Python» skulle bestå av 20 veiledende prinsipper for Python-programmering, men det er i dag bare 19 aforismer. La oss gå gjennom dem.
Vakkert er bedre enn stygt
Dette prinsippet understreker viktigheten av å skrive elegant og «Pythonic» kode.
Her er et eksempel på kode med dårlig stil:
def square(num):
squares = []
for i in range(num):
squares.append(i*i)
return squares
Denne funksjonen gjør følgende:
- Oppretter en tom liste.
- Bruker en løkke for å legge til elementer i listen.
- Returnerer listen.
Selv om koden er funksjonell, er den ikke «Pythonic» og kan være vanskelig å vedlikeholde.
En mer elegant løsning bruker generatorer. Her er en generatorfunksjon som tilsvarer den ovenfor:
def square(num):
for i in range(num):
yield i*i
Enda bedre er det å bruke et generatoruttrykk:
num = ...
squares = (i*i for i in range(num))
Eksplisitt er bedre enn implisitt
Når du skriver kode, bør du være tydelig med hensyn til funksjonen og ikke la andre utviklere gjette underforstått oppførsel. Unngå for eksempel wildcard-importer:
from some_module import * # wildcard import
from some_other_module import *
result = some_function() # hvor kom denne fra?
Dette er ineffektivt og gjør koden vanskelig å forstå. Det er bedre å importere funksjoner og klasser spesifikt:
from some_module import this_function # eksplisitt import
result = this_function() # nå vet vi det!
Enkelt er bedre enn komplekst
Hold koden enkel og unngå unødvendig kompleksitet. La oss se på et eksempel der vi skal reversere en streng. En rekursiv løsning kan se slik ut:
def reverse_string(my_string):
if my_string == "":
return my_string
else:
return reverse_string(my_string[1:]) + my_string[:1]
Dette fungerer, men er unødvendig komplisert. Det finnes enklere og mer «Pythonic» metoder.
For eksempel med string slicing:
>>> rev_string = my_string[::-1]
>>> rev_string
'nohtyP'
Eller ved bruk av innebygde metoder:
>>> rev_string = ''.join(reversed(my_string))
>>> rev_string
'nohtyP'
Kompleks er bedre enn komplisert
String-reversering er et enkelt eksempel. I praksis kan vi trenge mer kompleks logikk. Tenk deg at du skal koble til en database:
- Først må du parse en TOML-konfigurasjonsfil.
- Deretter må databasetilkoblingen være installert.
- Du må implementere feilhåndtering for tilkoblingsproblemer.
- Til slutt må du utføre spørringer mot databasen.
Dette er mer komplekst, men det trenger ikke å være komplisert. Bruk innebygde moduler effektivt og organiser koden slik at den er lett å forstå.
Flat er bedre enn nestet
En flat struktur er enklere å analysere enn en nestet struktur. Unngå overdreven granularitet i prosjektene dine.
Likevel er det situasjoner hvor du må gå utover en flat struktur. I slike tilfeller, hold hekkingen til et minimum.
Her er et eksempel:
from db_info.config.actions.parse.parse_config import parse_toml # vanskelig å analysere!
...
from db_config.parse_config import parse_toml # mye bedre!
...
Sparse er bedre enn tett
Når du begynner å programmere kan det være fristende å overbruke visse funksjoner i språket. List comprehensions er «Pythonic» men bør brukes der de er nødvendige.
Se på dette eksemplet:
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)]
List comprehension er her for tett og vanskelig å analysere. En `for`-løkke med betingelser ville vært mer lesbar.
Lesbarhet teller
Skriv alltid lesbar kode. Her er noen enkle måter å forbedre lesbarheten på:
- Bruk beskrivende variabelnavn.
- Legg til docstrings for funksjoner og klasser.
- Kommenter koden der det er nødvendig.
- Bruk type hints for argumenter og returtyper.
Spesielle tilfeller er ikke spesielle nok til å bryte reglene
Du bør i størst mulig grad følge reglene for språket og anbefalte beste praksis.
Men er det alltid mulig? Nei, og det er grunnen til neste aforisme.
Selv om det praktiske slår renhet
Selv om det anbefales å følge språkets regler, er det i visse tilfeller helt akseptabelt å ikke følge noen av prinsippene.
Feil skal aldri passere stille
Feil under kjøring er ganske vanlig i Python. Du bør alltid håndtere feil og ikke ignorere dem.
Implementer passende feilhåndtering for ulike typer feil:
try:
# gjør dette
except ErrorType1:
# gjør noe
except ErrorType2:
# gjør noe annet
...
Unngå generiske `except`-blokker. Nyere Python-versjoner støtter unntakskjeding og unntaksgrupper.
Med mindre det er eksplisitt tystet
Hvis designet tillater at feilen ignoreres, bør det gjøres eksplisitt. For eksempel, hvis du får `OperationalError` når du kobler til databasen, prøv med en standardkonfigurasjon:
try:
# kobler til med tilpasset config
except OperationalError:
# kobler til med standard config
I møte med tvetydighet, nekt fristelsen til å gjette
Ikke gjett. Test koden for å være sikker. For eksempel med tupler av boolske verdier:
>>> True, True == (True, True)
(True, False)
>>> True, (True == (True, True))
(True, False)
>>> (True, True) == (True, True)
True
Det bør være én – og helst bare én – åpenbar måte å gjøre det på
Det skal helst finnes én og kun én anbefalt «Pythonic» måte å gjøre ting på. I eksemplet med strengreversering har vi sett flere måter å gjøre det på.
Denne aforismen er en intern vits om inkonsistent bruk av tankestrek. Vi bruker vanligvis tankestreker uten mellomrom eller med mellomrom både foran og bak.
Dette viser at selv aforismen som sier at det skal være én måte å gjøre ting på, kan skrives på flere måter.
Selv om den måten kanskje ikke er åpenbar med mindre du er nederlandsk
Dette er en lett spøk med referanse til Guido Van Rossum, skaperen av Python (som er nederlandsk). Den mest «Pythonic» måten å gjøre noe på kommer kanskje naturlig for han, men vi andre trenger erfaring.
Nå er bedre enn aldri
Denne aforismen kan tolkes på flere måter.
En tolkning er at det er bedre å begynne å kode et prosjekt nå i stedet for å somle.
En annen tolkning er at kode som kjører raskt er bedre enn kode som har feil og går inn i en evig løkke.
Selv om det aldri ofte er bedre enn akkurat nå
Denne aforismen er motstridende til den forrige. Selv om vi ikke skal utsette, må vi tenke oss om før vi begynner å kode.
Det er en dårlig idé å kode en modul uten å tenke over problemet, da slik kode er vanskelig å refaktorisere.
Hvis implementeringen er vanskelig å forklare, er det en dårlig idé
Selv kompleks logikk kan implementeres på en måte som er lett å forklare og forstå.
Hvis implementasjonen er vanskelig å forklare er det sannsynligvis unødvendig komplisert, og koden bør refaktoreres.
Hvis implementeringen er enkel å forklare, kan det være en god idé
Dette følger den forrige aforismen. Hvis implementasjonen kan forklares enkelt, er det sannsynligvis en god idé.
Kode som er lett å forklare er ofte lesbar og lett å følge, med minimal kompleksitet.
Navnerom er en strålende idé – la oss bruke flere av dem!
I Python kan objekter nås ved hjelp av navnene deres i navnerommet. For eksempel vil alle forekomstvariablene være i forekomstens navnerom.
Dette lar oss bruke objekter med samme navn, uten at det skaper konflikter. Men bruk det med omhu slik at det ikke går utover lesbarheten.
Konklusjon
Det var alt for denne artikkelen! Jeg håper denne veiledningen har hjulpet deg med å forstå hvordan «The Zen of Python» legger vekt på kodestil og god kodepraksis i Python. Jo mer du koder, jo bedre blir du.
Hvis du er interessert i å lære mer om å skrive kort og lesbar kode, kan du lese denne artikkelen om Python one-liners.