Default-Argumente werden einmal ausgewertet, bei der Definition der Funktion, nicht bei jedem Aufruf. Eine Default-Liste oder ein Default-Dict ist deshalb ein einziges geteiltes Objekt, das über alle Aufrufe hinweg bestehen bleibt, sodass sich Mutationen anhäufen und zwischen Aufrufern leaken. Die Lösung ist, auf None zu defaulten und im Body einen frischen Container zu bauen, wenn das Argument None ist.
Warum Interviewer das fragen
Das ist ein schneller Test, ob du verstehst, dass ein def-Statement ausgeführt wird und Objekte zur Definitionszeit bindet. Interviewer mögen es, weil die falsche Antwort selbstsicher und konkret ist: Leute beharren darauf, dass die Liste pro Aufruf neu erzeugt wird. Es öffnet außerdem die Tür zum Unterschied zwischen dem Binden eines Namens und dem Kopieren eines Werts, der hinter vielen Python-Überraschungen steckt.
So baust du deine Antwort auf
- Sag, dass Defaults einmal zur Definitionszeit ausgewertet werden.
- Erklär die Konsequenz des geteilten Objekts.
- Gib die Lösung mit dem None-Sentinel.
- Merk an, dass unveränderliche Defaults sicher sind.
Beispielantwort
Weil das Default-Objekt einmal erzeugt wird, wenn Python das def-Statement ausführt, und danach bekommt jeder Aufruf, der das Argument weglässt, genau dieses Objekt. Ist es eine Liste und die Funktion hängt etwas an, sieht Aufruf drei, was Aufruf eins und zwei hinterlassen haben. Mich hat das bei einem Caching-Helper erwischt, der ein leeres Default-Dict mit Optionen nahm. In einem lang laufenden Worker ist das Dict tagelang gewachsen und irgendwann hat ein Request Einstellungen von einem völlig fremden Tenant geerbt, und das ist kein Bug, den man gern erklärt. Die Lösung ist langweilig: auf None defaulten, dann im Body explizit auf None prüfen und ein frisches Dict bauen, sodass ein absichtlich übergebenes leeres Dict weiterhin respektiert wird. Unveränderliche Defaults wie Integers, Strings oder None sind in Ordnung, weil nichts sie mutieren kann. Ruff meldet das ab Werk als B006, also ist es einer dieser Bugs, der in einem Projekt mit Linting in der CI nie bis ins Review kommen sollte.
Steht dieses Vorstellungsgespräch bald an? GhostPilot hört bei deinem Live-Call mit, erkennt die Frage in dem Moment, in dem sie gestellt wird, und bringt dir eine strukturierte Antwort in Echtzeit auf den Bildschirm. Probier es im nächsten Mock aus, oder hol dir einen $29 Session Pass, kein Abo, für den Ernstfall.
So funktioniert esNachfragen, mit denen du rechnen solltest
- Warum ist ein or statt einer expliziten None-Prüfung riskant?
- Sind Tupel als Defaults sicher?
- Wo überrascht die Auswertung zur Definitionszeit sonst noch?
Weitere Fragen für Python-Entwickler
Dein Interviewer stellt seine eigene Version davon. Kopier deine echte Stellenbeschreibung in den kostenlosen Question Predictor und bekomm die 20 Fragen, die diese Rolle am wahrscheinlichsten stellt, samt dem, worauf jede wirklich abzielt.
Meine Fragen vorhersagen