2017-12-03 5 views
-2
>>> mydict = {1: {45: 'ades', 54:'adee'}, 2: {68: 'gdes'}} 
>>> curr_value = mydict[1][45] 
>>> mydict[1][45] = 'zzzz' 
>>> print (curr_value) 
ades # Expected value: zzzz 

Wie kommt es, dass meine curr_value nicht mutiert von mydict? Ich habe curr_value oder irgendetwas nicht geklont.Veränderlichkeit in einem Wörterbuch

+3

Strings sind unveränderlich. 'current_value' enthält keine Referenz, da es ein' string' Objekt und keine 'liste' ist. – RottenCandy

+0

Oh ... Gibt es eine Methode, um auf den Punkt von 'Ades' zu verweisen? – user13123

+1

Warum fragen Sie nach dem Wörterbuch? 'curr_value' * referenziert nicht auf ein Dictionary-Objekt, und Sie können sich trivial vorstellen, dass sich das Dictionary * geändert hat. Es referenziert das String-Objekt, das vorher, aber nicht mehr, auch im Dictionary bei "mydict [1]" und damit indirekt von "mydict" bezeichnet wird. Sie könnten dies nützlich finden: https://nedbatchelder.com/text/names.html – jonrsharpe

Antwort

0
mydict = {1: {45: 'ades', 54:'adee'}, 2: {68: 'gdes'}} 
curr_value = mydict[1][45] 
mydict[1][45] = 'zzzz' 
print (curr_value) 
print(mydict) 

Ausgang:

ades 
{1: {45: 'zzzz', 54: 'adee'}, 2: {68: 'gdes'} 

Ihr Wörterbuch ist wandelbar - es wurde mutiert. Die curr_value ist eine Zeichenfolge und nicht änderbar.

midly annoing Idee:

def boll(tpl): 
    return mydict[tpl[0]][tpl[1]] 

mydict = {1: {45: 'ades', 54:'adee'}, 2: {68: 'gdes'}} 
curr_value = (1,45) 
print (boll(curr_value)) 
mydict[1][45] = 'zzzz' 
print (boll(curr_value)) 

Diese kapselt nur den Punkt innerhalb des dict Erinnern Sie verweisen möchten und die funtion bekommt man den Wert des dict im Moment Sie es nennen.

+0

Gibt es eine Methode, um den Punkt von 'Ades' zu verweisen? – user13123

+0

@ user13123 in Ihrem Fall: Verwenden Sie 'mydict [1] [45]', wenn sich der Wert ändert. Auf diese Weise erhältst du alles, was im Moment gespeichert ist. –

+0

Es gibt keine Notwendigkeit für diese Art von (Hinweis!) Sprache, und Sie haben gerade eine eingeschränkte Version von ['itemgetter'] (https://docs.python.org/3/library/operator.html#operator. itemgetter). – jonrsharpe

0

Es gibt keine Möglichkeit, eine einfache Variable zu erstellen, die sich selbst aktualisiert, wenn eine andere Datenstruktur aktualisiert wird. Diese Art von Verhalten kann nur mit einer Art von Ausdruck, wie einer Attribut- oder Gegenstandssuche, erreicht werden. Mit anderen Worten, können Sie ein Objekt curr_value so machen, dass in diesem Moment curr_value[0] gibt Ihnen den Wert von mydict[1][45] Auswertung oder curr_value.value Auswertung gibt Ihnen den Wert von mydict[1][45] in diesem Moment, aber man kann es nicht machen, so dass einfach nur curr_value Auswertung gibt Ihnen der Wert von mydict[1][45] in diesem Moment. Doing curr_value = mydict[1][45]immer setzt die curr_value zu dem, was es im Moment ist Sie zuweisen, und es wird später nicht aktualisiert, wenn mydict[1][45] ändert.

+0

Danke, ich verstehe jetzt. – user13123

0

Was Sie wollen, ist nicht möglich, weil einfache Zuweisung immer eine neue Bindung erstellt (d. H. Bindet das neue Objekt an den Namen auf der LHS des =-Zeichens). OTOH, eine Mutation durchführt schaffen keine neue Bindung, so dass Sie tun können, zB

ref = mydict[1] 
mydict[1][45] = 'zzzz' 
print(ref[45]) 

die zzzz druckt nach Wunsch.

Dieses Thema wird schön von Stack Overflow Veteran Ned Batchelder in Facts and myths about Python names and values abgedeckt und in Other languages have "variables", Python has "names" zusammengefasst.

Eine weitere Option ist

mydict = {1: {45: ['ades'], 54:['adee']}, 2: {68: ['gdes']}} 
ref = mydict[1][45] 
mydict[1][45][0]='zzzz' 
print(ref[0]) 

Allgemeinen zu tun, ist es am besten, wie das Erstellen von Unordnung zu vermeiden, aber manchmal diese Art der Sache ist nützlich. Wenn Sie beispielsweise einer 2D-Liste eine zusätzliche Indirektionsebene hinzufügen, können Sie sie sowohl über Spalten als auch über Zeilen zugänglich machen.

# Create the grid 
rows = [[[u+v] for u in 'abcd'] for v in 'wxyz'] 
cols = [list(u) for u in zip(*rows)] 
print(rows) 
print(cols) 
print() 

# Mutate some grid cells 
cell = rows[1][2] 
cell[0] = cell[0].upper() 
cell = cols[0][3] 
cell[0] = cell[0].upper() 

print(rows) 
print(cols) 

Ausgang

[[['aw'], ['bw'], ['cw'], ['dw']], [['ax'], ['bx'], ['cx'], ['dx']], [['ay'], ['by'], ['cy'], ['dy']], [['az'], ['bz'], ['cz'], ['dz']]] 
[[['aw'], ['ax'], ['ay'], ['az']], [['bw'], ['bx'], ['by'], ['bz']], [['cw'], ['cx'], ['cy'], ['cz']], [['dw'], ['dx'], ['dy'], ['dz']]] 

[[['aw'], ['bw'], ['cw'], ['dw']], [['ax'], ['bx'], ['CX'], ['dx']], [['ay'], ['by'], ['cy'], ['dy']], [['AZ'], ['bz'], ['cz'], ['dz']]] 
[[['aw'], ['ax'], ['ay'], ['AZ']], [['bw'], ['bx'], ['by'], ['bz']], [['cw'], ['CX'], ['cy'], ['cz']], [['dw'], ['dx'], ['dy'], ['dz']]] 

Zu Beginn dieser Antwort habe ich festgestellt, dass "einfache Zuordnung immer eine neue Bindung schafft". Jedoch wird augmented assignment eine In-Place-Operation durchführen, wenn dies möglich ist, d. H. Das Ziel ist ein veränderbares Objekt.Aus der Dokumentation:

Ein erweiterte Zuweisungsausdruck wie x += 1 kann neu geschrieben werden als x = x + 1 ein ähnliches zu erreichen, aber nicht genau die gleiche Wirkung. In der erweiterten Version wird x nur einmal ausgewertet. Außerdem wird, wenn möglich, der Ist-Vorgang vor Ort ausgeführt, was bedeutet, dass statt ein neues Objekt erstellt und dem Ziel zugewiesen wird, stattdessen das alte Objekt geändert wird.