2013-02-25 10 views
20

Ich bin sehr verwirrt durch das Verhalten unten. Die Fälle 1, 3 und 4 funktionieren wie erwartet, aber Fall 2 nicht. Warum erlaubt Fall 2 der Funktion, den Wert des Wörterbucheintrags global zu ändern, obwohl das Wörterbuch niemals von der Funktion zurückgegeben wird? Ein Hauptgrund, warum ich Funktionen verwende, besteht darin, alles in der Funktion vom Rest des Codes zu isolieren, aber dies scheint nicht möglich zu sein, wenn ich die gleichen Variablennamen innerhalb der Funktion verwende. Ich war der Auffassung, dass alles, was explizit in einer Funktion definiert ist, lokal für diese Funktion ist, aber dies scheint nicht der Fall zu sein, wenn das Wörterbuch definiert und als Eingabe an die Funktion übergeben wird.Python-Wörterbuch übergeben als eine Eingabe für eine Funktion wirkt wie ein globales in dieser Funktion anstelle einer lokalen

Python 2.7.2+ (default, Oct 4 2011, 20:06:09) 
[GCC 4.6.1] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 

============= Fall 1 ===============

>>> def testfun1(a): 
...  a=2 
... 
>>> a=0 
>>> testfun1(a) 
>>> a 
0 

====== ======= Fall 2 ===============

>>> def testfun2(b): 
...  b['test']=2 
... 
>>> b={} 
>>> testfun2(b) 
>>> b 
{'test': 2} 

============= Fall 3 ==== ===========

>>> def testfun3(): 
...  c=2 
... 
>>> c=0 
>>> testfun3() 
>>> c 
0 

============= Fall 4 =============== (von dieser Frage erklärt: Global dictionaries don't need keyword global to modify them?)

>>> def testfun4(): 
...  d['test']=10 
... 
>>> d={} 
>>> testfun4() 
>>> d 
{'test': 10} 

Antwort

35

Python's parameter passing acts a bit different than the languages you're probably used to. Anstatt einen expliziten Wert zu übergeben und eine Verweis-Semantik zu übergeben, hat Python seinen Namen. Sie übergeben im Wesentlichen immer das Objekt selbst, und die Veränderlichkeit des Objekts bestimmt, ob es geändert werden kann oder nicht. Listen und Dicts sind veränderbare Objekte. Zahlen, Strings und Tupel sind nicht.

Sie übergeben das Wörterbuch an die Funktion, keine Kopie. Wenn Sie es ändern, ändern Sie also auch die ursprüngliche Kopie.

Um dies zu vermeiden, sollten Sie zuerst das Wörterbuch vor dem Aufruf der Funktion oder innerhalb der Funktion kopieren (die Übergabe des Wörterbuchs an die dict Funktion sollte es tun).

+2

Zum Kopieren eines Wörterbuchs sollte man die Methode decopy des Kopiermoduls verwenden ** copy.deepcopy (d) **, die eine tiefe Kopie von d zurückgibt. Weitere Informationen zu seichten vs decopy finden Sie unter https://docs.python.org/2/library/copy.html –

+3

@PavanGupta Das kommt darauf an, wie tief 'eine Kopie Sie wollen. Wenn Sie ein Diktat haben, dessen Werte ebenfalls diktiert sind, möchten Sie Kopien dieser Diktate erstellen oder auf diese verweisen. Diese Regel/Frage gilt rekursiv. – Darthfett

1

Das globale Schlüsselwort wird für die Zuordnung nur erforderlich (und wahrscheinlich del, ich habe es nie versucht). Objektmutationen sind absolut gültig.

0

Sie haben ein Objekt dict an die Funktion übergeben und es in der Funktion geändert, so dass es natürlich nach der Rückgabe der Funktion geändert wird. Das Objekt wird nicht kopiert, sodass Sie dasselbe Objekt ändern, das Sie übergeben haben, und diese Frage hat nichts mit Namen, ähnlichen Namen, Bereichen usw. zu tun, da Sie das Objekt explizit übergeben haben.

0

Wenn Sie ein Basisobjekt wie eine ganze Zahl oder eine Zeichenfolge an eine Funktion übergeben, tritt bei der Änderung innerhalb der Funktion nichts auf das entsprechende Objekt außerhalb der Funktion ein. Wenn Sie mit einem Basisobjekt führen, übergibt Python es Wert.

Wenn Sie jedoch ein Wörterbuch oder eine Liste an eine Funktion übergeben, werden sie als Referenz übergeben, was bedeutet, dass Sie dieses Verhalten haben: Das Objekt außerhalb der Funktion wird geändert, wie Sie gesehen haben.

edit: Darüber hinaus gibt es einen Unterschied zwischen dem Durchgang Wert oder als Referenz: nach Wert, eine „Kopie“ des Objekts vorgenommen wird, um in der Funktion verwendet zu werden; als Referenz wird das exakt gleiche Objekt durch den Verweis geführt, und Änderungen daran innerhalb der Funktion sind außerhalb sichtbar. Per Definition übergibt Python seine unveränderlichen Objekte nach Wert und seine veränderbaren Objekte durch Verweis.

+0

Antwort könnte verbessert werden, indem darauf hingewiesen wird, dass Zeichenfolgen unveränderlich sind und Wörterbücher änderbar sind. Das ist der wahre Unterschied. Ein Basisobjekt ist an sich nicht wirklich "definiert". –

+0

@ScottLundberg Aber in anderen Sprachen wie c/C++ Strings sind veränderbar; die Tatsache, dass Strings in Python unveränderlich sind (d. h. grundlegende Objekte), ist ein Merkmal der Python-Sprache [sie könnten durch ein Array oder eine Liste von Zeichen - und Listen sind änderbar]. (mehr Infos in der aktualisierten Antwort ...) –

+0

Ich stimme dir zu, weshalb ich den Vorschlag gemacht habe, es klarer zu machen. –