Python列表不反映variables的变化
当我写这个代码:
polly = "alive" palin = ["parrot", polly] print(palin) polly = "dead" print(palin)
我以为会输出这个:
"['parrot', 'alive']" "['parrot', 'dead']"
但是,它不。 我如何得到它输出?
Pythonvariables保存对值的引用。 因此,当你定义palin
列表时,你传入polly
引用的值,而不是variables本身。
您应该将值想象成气球,variables是线程绑定到这些气球。 "alive"
是一个气球, polly
只是一个线程,而palin
列表有一个不同的线程绑定到同一个气球。 在Python中,列表仅仅是一系列线程,全部从0开始编号。
你接下来要做的是把polly
string绑定到一个新的"dead"
气球上,但是这个链表仍然保留着和"alive"
气球绑定的旧线程。
你可以把这个线程replace为列表中的"alive"
,方法是通过索引重新分配列表来引用每个线程; 在你的例子中是线程1
:
>>> palin[1] = polly >>> palin ['parrot', 'dead']
在这里,我简单地把palin[1]
线绑在一起, polly
与同样的东西绑在一起,不pipe可能如何。
请注意,Python中的任何集合,例如dict
, set
, tuple
等等都只是线程的集合。 其中一些可以将线程交换出来用于不同的线程,比如列表和字典,这就是python“mutable”中的一些东西。
另一方面,string是不可变的。 一旦你定义了一个像"dead"
或"alive"
的string,它就是一个气球。 你可以用一个线程(一个variables,一个列表或任何其他)绑定它,但是你不能replace它里面的字母。 你只能将该线程绑定到一个全新的string。
python中的大部分事情可以像气球一样。 整数,string,列表,函数,实例,类,都可以绑定到一个variables,或捆绑成一个容器。
您也可以阅读Ned Batchelder关于Python名称的论文 。
在您的第二个打印语句之前,将您的新值存储到palin
:
palin = ["parrot", polly]
当你把一个string放在一个列表中时,这个列表保存了一个string的副本。 string最初是一个variables,一个字面值,一个函数调用的结果,还是其他的东西都没有关系。 在列表看到它时,它只是一个string值。 稍后更改生成的string不会影响列表。
如果你想存储一个值的引用,当这个值发生变化的时候,通常的机制就是使用一个包含“引用”值的列表。 把这个应用到你的例子中,你得到了一个嵌套的列表:
polly = ["alive"] palin = ["parrot", polly] print(palin) polly[0] = "dead" print(palin)
该列表将只包含值,而不是您想要的variables的引用。 然而,你可以在列表中存储一个lambdaexpression式,并使lambdaexpression式查找variables的值。
>>> a = 'a' >>> list = ['a',lambda: a] >>> list[1] <function <lambda> at 0x7feff71dc500> >>> list[1]() 'a' >>> a = 'b' >>> list[1]() 'b'
你不能。 分配给一个裸名是Python总是只重新绑定名字,并且你不能自定义或者监视这个操作。
你可以做的是使polly
变成一个可变的对象而不是一个string,并改变它的值,而不是重新命名的名称。 一个简单的例子:
>>> polly = ['alive'] >>> items = ['parrot', polly] >>> items ['parrot', ['alive']] >>> polly[0] = 'dead' >>> items ['parrot', ['dead']]
其他答案已经解释了发生了什么事情。
这是激励使用对象的(几个)问题之一。 例如,可以这样做:
class Animal: def __init__(self, aniType, name): self.aniType = aniType self.name = name self.isAlive = True def kill(self): self.isAlive = False def getName(self): return self.name def getType(self): return self.aniType def isLiving(self): return self.isAlive polly = Animal("parrot", "polly") print(polly.getName()+' the '+polly.getType()+' is alive?') print(polly.isLiving()) polly.kill() print(polly.getName()+' the '+polly.getType()+' is alive?') print(polly.isLiving())
对于一个简单的任务来说,它可能看起来像很多代码,但对象往往是这样的事情的方式,因为它们有助于保持一切的组织。
这是该程序的输出:
polly the parrot is alive? True polly the parrot is alive? False