【发布时间】:2012-08-18 07:33:43
【问题描述】:
当我写这段代码时:
polly = "alive"
palin = ["parrot", polly]
print(palin)
polly = "dead"
print(palin)
我以为它会输出这个:
"['parrot', 'alive']"
"['parrot', 'dead']"
然而,事实并非如此。如何让它输出?
【问题讨论】:
当我写这段代码时:
polly = "alive"
palin = ["parrot", polly]
print(palin)
polly = "dead"
print(palin)
我以为它会输出这个:
"['parrot', 'alive']"
"['parrot', 'dead']"
然而,事实并非如此。如何让它输出?
【问题讨论】:
Python 变量持有对值的引用。因此,当您定义palin 列表时,您传入的是polly 引用的值,而不是变量本身。
您应该将值想象为气球,变量是与这些气球绑定的线程。 "alive" 是一个气球,polly 只是该气球的一个线程,而palin 列表有一个不同 线程绑定到同一个气球。在 python 中,列表就是一系列线程,所有线程都从 0 开始编号。
您接下来要做的是将polly 字符串绑定到新气球"dead",但列表仍保留与"alive" 气球绑定的旧线程。
您可以通过按索引重新分配列表以引用每个线程来将该线程替换为列表所持有的"alive";在您的示例中,这是线程 1:
>>> palin[1] = polly
>>> palin
['parrot', 'dead']
在这里,我只是将 palin[1] 线程绑定到 polly 所绑定的同一事物上,无论它可能是什么。
请注意,python 中的任何集合,例如dict、set、tuple 等,也只是线程的集合。其中一些可以将它们的线程换成不同的线程,例如列表和字典,这就是使 python 中的某些东西“可变”的原因。
另一方面,字符串是不可变的。一旦定义了"dead" 或"alive" 之类的字符串,它就是one 气球。您可以用线程(变量、列表或其他任何东西)将其绑定,但您不能替换其中的字母。您只能将该线程绑定到一个完全 new 字符串。
python 中的大多数东西都可以像气球一样工作。整数、字符串、列表、函数、实例、类,都可以绑定到变量或容器中。
【讨论】:
在您的第二个打印语句之前,将您的新值存储到palin:
palin = ["parrot", polly]
【讨论】:
polly 中的值,因此无法在其他任何地方更改它。行polly = "dead" 是rebinding operation rather than a mutating one
当您将字符串放入列表时,列表会保存该字符串的副本。字符串最初是变量、文字值、函数调用的结果还是其他东西都没有关系;当列表看到它时,它只是一个字符串值。更改以后生成的字符串永远不会影响列表。
如果您想存储对某个值的引用,该值会在该值更改时发出通知,通常的机制是使用包含“引用”值的列表。将其应用于您的示例,您将得到一个嵌套列表。示例:
polly = ["alive"]
palin = ["parrot", polly]
print(palin)
polly[0] = "dead"
print(palin)
【讨论】:
该列表将仅包含值,而不是您想要的变量引用。但是,您可以在列表中存储一个 lambda,并让 lambda 查找变量的值。
>>> a = 'a'
>>> list = ['a',lambda: a]
>>> list[1]
<function <lambda> at 0x7feff71dc500>
>>> list[1]()
'a'
>>> a = 'b'
>>> list[1]()
'b'
【讨论】:
lambda: a基本上是一个函数,它只返回存储在a中的值。这就是为什么你可以使用命令list[1]();这意味着您调用存储在list[1] 中的函数。 (另外,适当的 gravatar,@Jonatan)
你不能。给一个裸名赋值是 Python 总是只重新绑定这个名字,你不能自定义或监控这个操作。
您可以做的是使polly 成为可变对象而不是字符串,并改变其值而不是重新绑定名称。一个简单的例子:
>>> 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
【讨论】: