Python 列表不反映变量变化
- 2025-02-11 09:51:00
- admin 原创
- 54
问题描述:
当我写下这段代码时:
polly = "alive"
palin = ["parrot", polly]
print(palin)
polly = "dead"
print(palin)
我以为它会输出这个:
['parrot', 'alive']
['parrot', 'dead']
然而,事实并非如此。它确实输出:
['parrot', 'alive']
['parrot', 'alive']
我怎样才能让它输出那个(前者)?
解决方案 1:
Python 变量保存对值的引用。因此,定义列表时palin
,传入的是引用的值polly
,而不是变量本身。
您应该将值想象为气球,变量是与气球绑定的线程。"alive"
是一个气球,polly
只是与该气球绑定的线程,而palin
列表则有另一条线程与同一个气球绑定。在 Python 中,列表只是一系列线程,所有线程都从 0 开始编号。
接下来要做的就是把绳子系polly
到一个新气球上"dead"
,但是绳子仍然抓住了系在"alive"
气球上的旧线。
您可以通过索引重新分配列表来引用每个线程,从而将该线程替换"alive"
为列表所持有的线程;在您的示例中,那是线程1
:
>>> palin[1] = polly
>>> palin
['parrot', 'dead']
在这里我只是将palin[1]
线绑在同一个东西polly
上,无论它是什么。
请注意,python 中的任何集合(例如dict
、、等)也只是线程的集合。其中一些可以将其线程交换为不同的线程,例如列表和字典,这就是 python 中某些东西“可变”的原因set
。tuple
另一方面,字符串是不可变的。一旦你定义了一个字符串,比如"dead"
或"alive"
,它就变成了一个气球。你可以用线(变量、列表或其他任何东西)把它绑起来,但你不能替换里面的字母。你只能把那根线绑在一个全新的字符串上。
Python 中的大多数东西都可以像气球一样运作。整数、字符串、列表、函数、实例、类,都可以绑定到变量或绑定到容器中。
您可能还想阅读Ned Batchelder 关于 Python 名称的论文。
解决方案 2:
在第二个打印语句之前,将您的新值存储到palin
:
palin = ["parrot", polly]
解决方案 3:
当你将字符串放入列表中时,列表会保存该字符串的副本。无论字符串最初是变量、文字值、函数调用的结果还是其他内容,当列表看到它时,它只是一个字符串值。更改生成字符串的任何内容都不会影响列表。
如果您想要存储对某个值的引用,并在该值发生变化时发出通知,通常的机制是使用包含“引用”值的列表。将其应用到您的示例中,您会得到一个嵌套列表。示例:
polly = ["alive"]
palin = ["parrot", polly]
print(palin)
polly[0] = "dead"
print(palin)
解决方案 4:
该列表将仅包含值,而不是您想要的对变量的引用。但是,您可以在列表中存储 lambda,并让 lambda 查找变量的值。
>>> a = 'a'
>>> list = ['a',lambda: a]
>>> list[1]
<function <lambda> at 0x7feff71dc500>
>>> list[1]()
'a'
>>> a = 'b'
>>> list[1]()
'b'
解决方案 5:
你不能。分配给裸名称是 Python 始终只会重新绑定名称,并且你无法自定义或监视此操作。
你可以做的是创建polly
一个可变对象而不是字符串,并改变其值而不是重新绑定名称。一个简单的例子:
>>> polly = ['alive']
>>> items = ['parrot', polly]
>>> items
['parrot', ['alive']]
>>> polly[0] = 'dead'
>>> items
['parrot', ['dead']]
解决方案 6:
其他答案已经很好地解释了发生了什么。
这是促使使用对象的(几个)问题之一。例如,可以这样做:
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