在Python中将变量存储在列表中

在Python中将变量存储在列表中,python,python-2.7,Python,Python 2.7,我有一段Python 2.7代码,用于查询设备的移动限制: pan_low_limit = int(self.send_query("PN", 2)) pan_high_limit = int(self.send_query("PX", 2)) tilt_low_limit = int(self.send_query("TN", 2)) tilt_high_limit = int(self.send_query("TX", 2)) 我想我可以写得更好,比如: limits = [(pan_lo

我有一段Python 2.7代码,用于查询设备的移动限制:

pan_low_limit = int(self.send_query("PN", 2))
pan_high_limit = int(self.send_query("PX", 2))
tilt_low_limit = int(self.send_query("TN", 2))
tilt_high_limit = int(self.send_query("TX", 2))
我想我可以写得更好,比如:

limits = [(pan_low_limit, "PN"), (pan_high_limit, "PX"), (tilt_low_limit, "TN"), (tilt_high_limit, "TX")]
for v, c in limits:
    v = int(self.send_query(c, 2))
    print("Result from {}: {}".format(c, v))
print(limits)
print("tilt_low_limit: {}".format(tilt_low_limit))
打印报表是为了发现发生了什么。当我运行它时,我得到以下输出(在这段代码之前,这四个变量已经用值1初始化):

我真的不明白发生了什么。“v=int(self.send_query(c,2))”中的v值似乎是我所期望的,但在下一行,这些变量又有了旧值?

这是您想要的:

for i, (v, c) in enumerate(limits):
    limits[i] = int(self.send_query(c, 2))
v=
不会更改
limits
中的值,它只会更改引用/变量
v

在Python中,符号名(如代码中的
pan\u low\u limit
)是对值的引用(如“-27067”)

当一个名称分配给另一个名称时(就像代码中的
限制
v
一样),新名称将成为该值的附加引用。在您的情况下,在分配前的第一次迭代中,名称:
pan\u low\u limit
limits[0][0]
v
均指相同的值:

但是,将名称指定(或绑定)给新值时,只有该名称才会引用新值。在您的情况下,任务完成后,您将有:

要获得所需的结果,应该更改变量,而不是重新分配它,以便所有引用都引用相同的新值。但是,在Python中,整数是不可变的,因此不能更改它。 解决方案是使用可变的东西,例如列表

如果您有一个可变变量,那么可以更改原始值以获得您期望的结果。您可以在以下两个代码段中看到这种差异:

使用整数:

pan_low_limit = 1
pan_high_limit = 1
tilt_low_limit = 1
tilt_high_limit = 1

limits = [(pan_low_limit, "PN"), (pan_high_limit, "PX"), (tilt_low_limit, "TN"), (tilt_high_limit, "TX")]
for v, c in limits:
    v = 2
    print("Result from {}: {}".format(c, v))
print(limits)
print("tilt_low_limit: {}".format(tilt_low_limit))
结果:

Result from PN: 2
Result from PX: 2
Result from TN: 2
Result from TX: 2
[(1, 'PN'), (1, 'PX'), (1, 'TN'), (1, 'TX')]
tilt_low_limit: 1
Result from PN: [2]
Result from PX: [2]
Result from TN: [2]
Result from TX: [2]
[([2], 'PN'), ([2], 'PX'), ([2], 'TN'), ([2], 'TX')]
tilt_low_limit: [2]
使用列表,我们可以修改值,而不是重新分配:

pan_low_limit = [1]
pan_high_limit = [1]
tilt_low_limit = [1]
tilt_high_limit = [1]

limits = [(pan_low_limit, "PN"), (pan_high_limit, "PX"), (tilt_low_limit, "TN"), (tilt_high_limit, "TX")]
for v, c in limits:
    v[0] = 2
    print("Result from {}: {}".format(c, v))
print(limits)
print("tilt_low_limit: {}".format(tilt_low_limit))
结果:

Result from PN: 2
Result from PX: 2
Result from TN: 2
Result from TX: 2
[(1, 'PN'), (1, 'PX'), (1, 'TN'), (1, 'TX')]
tilt_low_limit: 1
Result from PN: [2]
Result from PX: [2]
Result from TN: [2]
Result from TX: [2]
[([2], 'PN'), ([2], 'PX'), ([2], 'TN'), ([2], 'TX')]
tilt_low_limit: [2]
参考:


感谢@bruno desthuilliers指出了之前答案中的缺陷

Python的变量不是内存地址的符号名(如C或Pascal),而是绑定到对象的名称。重新绑定名称只会使此名称指向另一个对象,不会影响以前绑定到此名称的对象。您想阅读本文以获得更深入的解释:我不完全理解您的意思,因此我将仔细阅读您提供的链接。@Brunodesshuillers该链接非常有用,并澄清了很多问题。推荐阅读。我还发现pythontutor.com有助于将变量/对象在小代码片段中的行为可视化,但这似乎不起作用。在“for”循环之后,limits=[-2706727067,-27999333]。然而,变量的值pan_low_limit/。。。都仍然是1。@DieterVansteenwegenON4DD是的,没有办法以您喜欢的方式修改变量(除非它们是全局变量,在这种情况下,您可以修改
globals()
dict,但不要这样做)。所以我建议一个合理的选择。抱歉,说它“类似于C中的赋值”是完全错误的。如果用struct而不是int重写C示例,您会发现更改
a
的一个字段不会影响
b[0]
,因为它确实会复制“值”——而在Python中(使用任何可变对象),通过迭代变量改变对象(或指向此对象的任何其他名称)确实更改了列表中存储的名称。长话短说:Python的“变量”与C变量没有任何共同之处,您无法用一个it术语解释另一个。感谢您指出这一点。我确实过于简化了。我现在更新了答案。这更好,但仍然是错误的;-)INT是不可变的事实实际上是完全不相关的,问题是重新绑定名称只会使名称引用另一个对象。对于可变对象,行为将是相同的。区别不在可变对象和不可变对象之间,而是在变异和重新绑定之间。我不完全理解你的意思。可能需要更详细的解释。正如您在我的示例中所看到的,如果变量是可变的或不可变的,则会产生不同。看看这个答案,我想你应该提供一个新的答案,详细说明你的理论,参考资料和一些证明它的代码。我很乐意投票支持它:)是的,我同意在一种情况下我变异了它,而在另一种情况下我没有,因为它是不可变的:)。我也同意,如果您的答案是“python就是这样工作的,句号”,那么最好不要提供新的答案。您自己的参考清楚地说明了为什么可变和不可变在这个场景中是相关的。我链接的问题也解释了这一点。