Python Saug Punkte contd.

written by Martin HĂ€cker on

Eine Sache die mich bei Python immer wieder Ă€rgert ist die Tatsache dass Standardwerte fĂŒr Methodenargumente zur Parsezeit festgelegt werden anstatt zur Aufrufzeit.

Das ist total doof, denn dadurch teilen sich alle aufrufe der Funktion den gleichen default-wert - was zwar schön schnell sein mag, aber trotzdem in fast allen FÀllen nur bei nicht verÀnderbaren Objekten (so wie Integer und Strings) Sinn ergibt.

So fĂŒhrt das dazu dass man in Python eine ganze Menge Workarounds braucht um mit default-argumenten zu arbeiten.

Das wichtigste dabei ist der default typ None. Das ist der workaround fĂŒr alle mutable-objekte, da man die in fast keinem Fall zwischen verschiedenen Methodenaufrufen teilen möchte. So sieht das aus:

def end_poll(self, end_time=None):
    if end_time is None:
        end_time = datetime.utcnow()
    # work with end_time...

Der Punkt hier ist dass man datetime.utcnow() nicht in das standard Argument hineinschreiben kann, da man sonst bei jedem Aufruf der Methode den gleichen Wert hĂ€tte: Die Parsezeit. Nicht sonderlich nĂŒtzlich.

Das hat zur Folge dass man:

  • aus der Signatur nicht sehen was das Standardargument ist (utc/gmt oder vielleicht ewas ganz anderes?). Immerhin gibt es inzwischen immer mehr IDEs die diese Signatur beim aufrufen fĂŒr autocompletion nutzen oder sie wenigstens anzeigen können.
  • Man beim verwenden von Standardargumenten immer ĂŒberlegen muss ob man dieses Argument jetzt in die Methodendefinition oder in den Body aufnehmen muss.
  • fĂŒr jedes Standardargument noch mal zwei extra Zeilen braucht. Das nervt vor allem deswegen weil man sich mit den standard Argumenten ja Zeilen sparen möchte. Das heißt die Kosten fĂŒr Standard-Argumente steigen und man benutzt sie seltener.
  • die default argumente noch mal separat dokumentieren muss, da ein dokumentations-extraktions-Werkzeug ja den Code nicht sieht, der das tatsĂ€chliche Standardargument setzt. Und natĂŒrlich hat man dann noch mal DRY verletzt da die Information jetzt zwei mal da steht.
  • richtig fiese Bugs kriegt, weil viele Leute diese Probleme nicht kennen oder sie ab und an vergessen und mal ein list(), dict() oder set() als Standardwert nehmen was dan fĂŒr viel Freude beim Debuggen sorgt.

Also, know your Python und vorsicht mit Standardargumenten!

Vielleicht kriegen wir ja irgendwann von unserem BDFL ein from __future__ import runtime_standard_argument_evaluation.