Cursus

Wat is de Zen van Python?
De Zen van Python is een set van negentien aforismen die dienen als leidende principes voor het ontwerp van Python. Het hadden er eigenlijk twintig moeten zijn; maar Guido van Rossum, de bedenker van Python, heeft het laatste aforisme nog steeds niet toegevoegd zoals bedoeld door Tim Peters, de maker van de Zen van Python. Guido zou hebben gezegd dat het ontbrekende twintigste aforisme „een of andere bizarre insidegrap van Tim Peters” is.
Ondanks het ontbrekende twintigste aforisme werd de Zen van Python in 2004 gestandaardiseerd als PEP 20 vanwege de grote invloed op het ontwikkelproces van Python-programmeurs. Het volgen van de Zen van Python is niet verplicht, maar het kennen en in gedachten houden ervan is aan te raden. Als je de lessen ooit vergeet, kun je je geheugen eenvoudig opfrissen door import this uit te voeren in de Python-interpreter.
>>> 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!
In dit artikel bespreken we elke les in meer detail.
#1 Mooi is beter dan lelijk
Als je programmeur bent, staat vast dat je zeer vaardig bent. Problemen oplossen met code is niet eenvoudig, maar als Pythonista wordt er meer van je verwacht. Mooie code is beter dan lelijke code. Pythons snelle opmars is deels te danken aan de toegankelijkheid: het is simpel, leesbaar en elegant. Als Python-ontwikkelaar heb je de verantwoordelijkheid om de pythonische standaard hoog te houden door mooie code te schrijven.
Wat is mooie code? Dat is subjectief – schoonheid ligt in het oog van de toeschouwer en zo verder. Een simpele vuistregel om jezelf in toom te houden: schrijf schone, leesbare code die door andere ontwikkelaars gemakkelijk te begrijpen is. Bijvoorbeeld:
"""
Initial code was created by Vishal Sharma
See: https://towardsdatascience.com/the-zen-of-python-a-guide-to-pythons-design-principles-93f3f76d088a
"""
def collatz(num):
if num % 2 == 0:
return num // 2
else:
return 3 * num + 1
number = input("Enter a number: ")
while number != 1:
number = collatz(int(number))
print(number)
"""
Enter a number: 5
16
8
4
2
1
"""
De bovenstaande code werkt prima, maar is niet per se mooi. We hebben een onnodige else-conditie in onze collatz-functie die we als volgt kunnen verwijderen:
def collatz(num):
if num % 2 == 0:
return num // 2
return 3 * num + 1
Kortom, als je twee werkende stukjes code hebt, kies dan voor de versie die eenvoudiger, leesbaarder en makkelijker te begrijpen is.
#2 Expliciet is beter dan impliciet
Een aforisme „zelfverklarend” noemen is een grote fout – toch zie je mensen het doen. De kern van „expliciet is beter dan impliciet” is dat breedsprakige code te verkiezen is boven indirecte code. Doe er alles aan om te zorgen dat de functionaliteit van je code niet verborgen zit achter obscure taal. Iemand zonder voorkennis van je programma moet nog steeds kunnen begrijpen wat er in je code gebeurt.
#3 Simpel is beter dan complex
Je zou waarschijnlijk lachen als je maat een hogedrukreiniger tevoorschijn haalt om na het eten de afwas te doen. Niet alleen is het een bijzonder onhandige oplossing, de kans is ook groot dat de borden beschadigd raken. Op dezelfde manier is een zeer complexe oplossing toepassen op een simpel programmeerprobleem extreem onpraktisch. Er is geen reden om je oplossing nodeloos te compliceren, ook niet als je denkt dat het je slimmer doet lijken. Je kunt meer schade aanrichten dan goeddoen, en in Python wordt dat niet gewaardeerd.
Kijk eens naar deze functie die een string omkeert:
def reverse_string(string):
if len(string) == 1:
return string
else:
return reverse_string(string[1:]) + string[0]
string = "kurtis"
print(reverse_string(string))
"""
sitruk
"""
De code hierboven lost het probleem zeker op, maar is onnodig complex. Als je goed thuis bent in Python, weet je dat je een string kunt omkeren met indexing.
string = "kurtis"
# annonymous function solution
reverse_string = lambda x: x[::-1]
# function solution
def reverse(string):
return string[::-1]
print(reverse_string(string))
print(reverse(string))
"""
sitruk
sitruk
"""
#4 Complex is beter dan gecompliceerd
Afwassen met een hogedrukreiniger is onpraktisch: je bent beter af met een simpele oplossing zoals stromend kraanwater. Maar wat als het probleem is om een 4x4 Range Rover schoon te maken? Het vorige aforisme en dit aforisme herinneren ons eraan dat zowel simpele als complexe technieken kunnen worden toegepast om één probleem op te lossen. Een 4x4 Range Rover schoonmaken is geen simpel probleem en proberen dezelfde technieken toe te passen als bij de afwas kan werken, maar is gecompliceerder dan een hogedrukreiniger gebruiken. Kies dus voor eenvoud boven complexiteit, maar in situaties waar eenvoud onpraktisch is, kun je beter voor complexiteit gaan – ken de grenzen van eenvoud.
#5 Vlak is beter dan genest
Programmeurs houden ervan om dingen te organiseren in categorieën, subcategorieën en sub-subcategorieën om functionaliteit te scheiden. Hoewel het ordelijk klinkt, kan code op die manier organiseren tot meer verwarring leiden dan tot orde.
Er is niets mis mee om al je code in één module op het hoogste niveau te plaatsen: zo hoef je niet iets als from spam.foo.bar.john.doe import chicken te doen om een specifieke functionaliteit te benaderen. Hoe meer subcategorieën je toevoegt, hoe gecompliceerder je code wordt. Doe er alles aan om, waar mogelijk, bij een vlakke structuur te blijven.
#6 Spaarzaam is beter dan dicht opeen
Programmeurs worden gezien als een van de intelligentste mensen, dus er is geen reden om je intellect te benadrukken met overdreven slimme hacks. De meest gehoorde is „hoe je [een ingewikkelde taak] in 1 regel code doet.” Soms zijn one-liners te rechtvaardigen, maar vermijd situaties waarin je de leesbaarheid opoffert om alle functionaliteit in één regel te proppen.
Neem dit stukje code als voorbeeld:
"""
Code source Al Sweigart
See: https://inventwithpython.com/blog/author/al-sweigart.html0
"""
print('\n'.join("%i bytes = %i bits which has %i possible values." % (j, j*8, 256**j-1) for j in (1 << i for i in range(8))))
"""
1 bytes = 8 bits which has 255 possible values.
2 bytes = 16 bits which has 65535 possible values.
4 bytes = 32 bits which has 4294967295 possible values.
8 bytes = 64 bits which has 18446744073709551615 possible values.
16 bytes = 128 bits which has 340282366920938463463374607431768211455 possible values.
32 bytes = 256 bits which has 115792089237316195423570985008687907853269984665640564039457584007913129639935 possible values.
64 bytes = 512 bits which has 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095 possible values.
128 bytes = 1024 bits which has 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 possible values.
"""
De code werkt zeker, maar het is een nachtmerrie om te begrijpen: het is dicht opeengepakt en lastig te lezen.
Laten we kijken hoe dezelfde code eruitziet als we haar spaarzaam schrijven:
# Sparse example
bytes_and_bits = {j: j*8 for j in (1 << i for i in range(8))}
for bytes, bits in bytes_and_bits.items():
print(f"{bytes} bytes = {bits} which has {256**bytes-1} possible values")
"""
1 bytes = 8 which has 255 possible values
2 bytes = 16 which has 65535 possible values
4 bytes = 32 which has 4294967295 possible values
8 bytes = 64 which has 18446744073709551615 possible values
16 bytes = 128 which has 340282366920938463463374607431768211455 possible values
32 bytes = 256 which has 115792089237316195423570985008687907853269984665640564039457584007913129639935 possible values
64 bytes = 512 which has 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095 possible values
128 bytes = 1024 which has 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 possible values
"""
De bovenstaande code is veel makkelijker te lezen en doet precies hetzelfde als de one-liner.
#7 Leesbaarheid telt
Als je het nog niet had geraden: in Python telt leesbaarheid. Jouw taak is om de code één keer te schrijven. Maar er is een goede kans dat die meerdere keren gelezen wordt. Houd dat in gedachten: klinkers weglaten uit variabele- en functienamen is geen goed idee. In een situatie waarin je een functie create_lst of create_list kunt noemen, kies je voor de laatste.
#8 Uitzonderingen zijn niet bijzonder genoeg om de regels te breken
Python [en programmeren in het algemeen] zit vol met best practices om na te leven. Het is beter om best practices te volgen dan je eigen weg te gaan, want dat leidt vaak tot inconsistente, onleesbare code.
#9 Hoewel praktische bruikbaarheid belangrijker is dan puurheid
Les negen is een uitbreiding op les acht. Ja, het is beter om best practices te volgen, maar je in bochten wringen om je aan de regels te houden kan ook resulteren in onleesbare code. Dus iedere regel kan een uitzondering hebben. Als jouw manier om een probleem op te lossen praktischer, leesbaarder en makkelijker te begrijpen is, is het beter om af te wijken van de gevestigde best practices.
#10 Fouten mogen nooit stilletjes voorbijgaan
Een stille fout is wanneer een programma een foutcode of None teruggeeft in plaats van een uitzondering op te werpen. Het is beter dat een programma crasht dan dat de fout wordt verzwegen en het blijft doorlopen. Op de lange termijn kan het stillen van fouten leiden tot bugs in je programma die veel lastiger te verhelpen zijn.
#11 Tenzij expliciet gesmoord
Les elf is een uitbreiding op les tien. Soms wil je fouten die door je programma worden veroorzaakt negeren. In zulke gevallen is het best practice om de fout expliciet in je code te smoren.
#12 Bij ambiguïteit: weersta de verleiding om te gokken
Computers doen alleen wat wij ze zeggen: als je code zich niet gedraagt zoals jij wilt, dan komt dat omdat ze doet wat jij haar hebt opgedragen. Proberen het gedrag te repareren door op goed geluk verschillende oplossingen te proberen totdat er één werkt, is een slechte strategie – je maskeert mogelijk het probleem in plaats van het op te lossen. Weersta de verleiding. Denk in plaats daarvan de logica van het probleem door en pas kritisch denken toe om tot een passende oplossing te komen.
#13 Er zou één – en bij voorkeur maar één – voor de hand liggende manier moeten zijn om het te doen
Het motto van de programmeertaal Perl luidt: „There’s more than one way to do it!” Te veel opties leiden vaak tot keuzestress. Iets soortgelijks gebeurt wanneer er meerdere manieren zijn om code te schrijven die hetzelfde doel bereikt. Je hebt meer flexibiliteit in hoe je code schrijft, maar nu moet je alle mogelijke manieren leren waarop de code geschreven had kunnen zijn om haar te kunnen lezen: het extra werk om alle scenario’s te leren is onnodig.
#14 Hoewel die manier niet meteen voor de hand hoeft te liggen, tenzij je Nederlands bent
Dit aforisme laat de humor van Tim Peters zien: Guido van Rossum, bedenker van de programmeertaal Python en Benevolent Dictator For Life (BDFL) voor Python, is Nederlander. Het is een grapje om ons eraan te herinneren dat het begrijpen en onthouden van de taalregels van Python voor iedereen lastig is, behalve voor de bedenker zelf.
#15 Nu is beter dan nooit
Dit aforisme vertelt ons dat code die vastloopt in een oneindige lus of hangt, erger is dan code die dat niet doet.
#16 Hoewel nooit vaak beter is dan *meteen* nu
In het verlengde van les zestien: het is beter te wachten tot je programma klaar is met uitvoeren dan het vroegtijdig te beëindigen en onjuiste resultaten te krijgen.
#17 Als de implementatie moeilijk is uit te leggen, is het een slecht idee
Het is niet genoeg dat jij je eigen implementaties begrijpt – „ik weet wat ik bedoel” is geen argument. Programmeren is een teamsport, en als je je implementatie niet aan je teamgenoten kunt uitleggen, is de kans groot dat je de oplossing te ingewikkeld hebt gemaakt.
#18 Als de implementatie makkelijk is uit te leggen, is het mogelijk een goed idee
Maar: makkelijk uit te leggen code is niet per se goede code – het betekent alleen dat ze makkelijk uit te leggen is. Je kunt nog steeds slechte code hebben, maar het feit dat ze makkelijk uit te leggen is, betekent dat je op de goede weg bent.
#19 Naamruimten zijn een beregoed idee – laten we er meer van doen!
Een naamruimte is een abstractie in Python om namen te organiseren die aan objecten in een programma zijn toegekend. Met een bepaalde naamruimte en scope kan Python bepalen naar welk object je verwijst wanneer je een symbolische naam aanroept. Dit aforisme zegt simpelweg dat de manier waarop Python de symbolische namen onder de motorkap organiseert, behoorlijk geweldig is.
Conclusie
In dit artikel hebben we onze interpretatie van de Zen van Python gepresenteerd: richtlijnen die Python-programmeurs stimuleren om schone, leesbare code te schrijven. Sommigen zien de Zen van Python als het ultieme blauwdruk voor moeiteloos code schrijven, anderen nemen het wat minder serieus. Wij raden je aan de principes op je eigen code toe te passen om zelf te zien hoe ze je werk kunnen verbeteren. Wil je meer leren over het schrijven van geoptimaliseerde code, bekijk dan DataCamps Writing Efficient Python Code.
