Python-Funktion Anrufe sind Blutungen Umfang, stateful, nicht zu initialisieren Parameter?

Bevor ich die Kühnheit habe, einen Fehlerbericht einzureichen, dachte ich, dass ich meine Annahmen unter klügeren Pythonistas hier überprüfen würde. Ich habe heute einen verblüffenden Fall erlebt, also habe ich ihn auf ein Spielzeug-Beispiel gelegt, das unten gezeigt wird:

#!/usr/bin/env python # -*- coding: UTF-8 -*- """ A little script to demonstrate that a function won't re-initialize its list parameters between calls, but instead allows them to retain state. """ def bleedscope(a=[], b=[]): """ On each call, unless explicitly passed, both `a` and `b` should be initialized as empty lists. """ c = a if b: c.extend(b) return len(c) x = bleedscope(b=[1]) print x # Should be 1, as expected. x = bleedscope(b=[2]) print x # Expect also to be 1, but it's 2. `a` is retained. x = bleedscope(a=[1]) print x # Now 1 as expected. x = bleedscope(b=[3]) print x # 1 as expected? No, it's 3! Insanity! 

Ich dachte, funktionale Argumente waren lokal im Umfang der Funktion, und wurden Müll gesammelt am Ende eines Funktionsaufrufs, niemals den Zustand zwischen ihnen zu behalten. Ich habe das obige Skript auf Python 2.5.2 und Python 2.6.1 getestet, und mein Verständnis nicht die Ergebnisse. Argument a gewisser Zustand behält zwischen den meisten dieser Anrufe; Der am meisten verwirrend ist der letzte Aufruf zum bleedscope , wo er den Zustand des vorherigen Anrufs überspringt und am Ende des zweiten (dh [1, 2] ) in den Zustand zurückkehrt. [Ich schlage vor, dies in deinem Lieblings-Debugger zu sehen, um selbst zu sehen. Wenn du keinen hast, schlage ich Winpdb als soliden FOSS-Standalone-Python-Debugger vor.]

Was ist denn hier los?

4 Solutions collect form web for “Python-Funktion Anrufe sind Blutungen Umfang, stateful, nicht zu initialisieren Parameter?”

In Python werden die Standardparameterwerte nur dann initialisiert, wenn der def-Aufruf analysiert wird. Im Falle eines Objekts (wie zB deiner Listen) wird es zwischen Anrufen wiederverwendet. Werfen Sie einen Blick auf diesen Artikel darüber, was auch die notwendige Problemumgehung bietet:

http://effbot.org/zone/default-values.htm

Das ist Dein Problem:

 def bleedscope(a=[], b=[]): 

es sollte sein

 def bleedscope(a=None, b=None): if a is None: a = [] if b is None: b = [] 

Die Standardparameter werden nur einmal ausgeführt, wenn die Funktion analysiert wird. Dabei werden immer die gleichen 2 Listen verwendet.

Es ist eine FAQ .

Lustig genug, Ihre Eingabe und Ihre Ausgabe sind ganz ähnlich, aus völlig zufälligen Gründen.

Eigentlich passiert mit Python, dass die Standardwerte für a und b in Ihrer Methodendeklaration "statische" Werte sind. Sie werden einmal bei der Methodendefinition instanziiert. So wird dein Standard "a" jedes Mal gedrückt, wenn du kein "a" als Argument passierst.

Setzen Sie einen "print a" am Anfang Ihrer Methode, um zu sehen, dass passieren

  • Was bedeutet Umfang
  • Variable Bereiche in Python-Klassen
  • Python - Wie man eine globale Variable aus einer Funktion
  • Python: Wie kann ich eval () im lokalen Gültigkeitsbereich einer Funktion ausführen?
  • Warum erbt keine Unterfunktion den Bereich in Python?
  • __main__ und scoping in python
  • Kurze Beschreibung der Scoping Regeln?
  • Zweifel über python variablen Bereich
  • Python eval (kompilieren (...), Sandkasten), Globals gehen in Sandbox, wenn nicht in def, warum?
  • Python: Variablen sind noch zugänglich, wenn in try oder if definiert?
  • Warum verschachtelte Funktionen auf Variablen von äußeren Funktionen zugreifen können, aber sie nicht ändern dürfen [duplizieren]
  • Python ist die beste Programmiersprache der Welt.