设置项目时列表引用会发生什么

时间:2013-03-16 23:47:17

标签: python dictionary variable-assignment

def foo():
    testdict = {'A': '1235', 'B': '6458', 'C': 54156}
    dofoo(testdict)

def dofoo(testdict):
    testdict['A'] = testdict['A'].replace('2', '')

设置testdict时对testdict['A']变量的值的引用发生了什么?只有那个项目丢失了对原始值的引用吗?

修改

因为如果我愿意的话:

def foo():
    testdict = {'A': '1235', 'B': '6458', 'C': 54156}
    dofoo(testdict)

def dofoo(testdict)
    testdict = {'F' : '156', 'G' : '6875'}

然后参考将丢失。那么为什么不设置这样的集合项呢?

2 个答案:

答案 0 :(得分:2)

testdict = {'A': '1235', 'B': '6458', 'C': 54156}

def foo(x):
    x['A'] = 0;

foo(testdict)

print testdict['A']

testdict ['A']的输出为0。

这是因为dict作为引用传递给foo函数。

因此,当你将testdict传递给foo时,x不是一个新的dict,它是testdict的副本 - 它实际上是指向同一个testdict的指针。当x ['A']改变时,这意味着testdict ['A']也会改变。

答案 1 :(得分:2)

在任何给定时间,了解您使用给定名称所指的值是很重要的。这就是我的意思:

def doFoo1(testdict):
    testdict["A"] = "test1" # this changes a value contained in testdict
    print(id(testdict)) # the id

def doFoo2(testdict):
    testdict = {some:"new dict"} # this creates a new dict object
    print(id(testdict)) # prints a different id, since testdict is a new object

def foo():
    mydict = {'A': '1235', 'B': '6458', 'C': 54156}
    print(id(mydict))
    doFoo1(mydict)
    print(id(mydict))
    doFoo2(mydict)
    print(id(mydict))

这是我系统上的输出(Windows 7上的64位Python 3.3):

>>> foo()
59383560
59383560
59383560
59413832
59383560

打印了五个id值,来自foo的三个(第一个,第三个和第五个)以及每个doFoo个函数中的一个(第二个和第四个)。 doFoo2中唯一一个与其他的不同,因为语句testdict = {some:"new dict"}创建了一个新对象,该对象绑定到该函数命名空间内的testdict名称。该更改未反映在foo函数中,因为它的mydict名称仍绑定到原始对象。

这是Python的一部分,与大多数其他编程语言不同。与C(其中变量名称对应于内存中的特定位置)不同,在Python中,名称是指特定对象。如果再次指定名称,则只需将名称重新绑定到另一个对象(根本不会影响原始对象,但如果没有其他引用则可能会进行垃圾回收)。

Code like a Pythonista演示文稿的一部分非常有助于理解这种区别。我认为它的“名称标签”比喻非常适合理解名称绑定在Python中的工作原理。