循环遍历 Python、reference/assignment 中的对象列表时出现意外
Looping over a list of objects in Python, reference/assignment works unexpectedly
我有一些代码可以满足我的需要,但我希望它不会。我希望它应该被破坏,但它确实有效。
我一直在尝试从对象列表中查找并跟踪最佳*实例,并且每次我找到 successor_state
比当前的 best_sucessor_state
更好*。
在 for 循环的每个循环中,变量 successor_state
被分配(?)到 [=20= 生成的 state
对象列表中的新 state
实例]
因为我正在分配(?)best_sucessor_state
变量 successor_state
,我不明白为什么 best_successor_state
被分配到的基础状态(?)不更新每个时间 for-loop 循环和变量 successor state
被分配(?)到 current_state.successor_states()
列表中的新 state
。
如果有人能解释以下内容,我将不胜感激:
- 为什么会这样?
- 如果我想破坏我的代码并让
best_successor_state
跟上循环中 successor_state
的变化,我该怎么做?
- 我应该使用什么准确的语言("assignment/referencing"、"variable/label/name")?
*best:state
class有一个计算值的方法,叫做objective_function
,越低越好
这是代码,非常感谢:
def steepest_ascent_HCS(initial_state, objective_function):
current_state = initial_state
while True:
current_state_value = objective_function(current_state)
best_successor_state_value = float('inf')
for successor_state in current_state.successor_states():
successor_state_value = objective_function(successor_state)
if successor_state_value < best_successor_state_value:
best_successor_state = successor_state
best_successor_state_value = successor_state_value
if best_successor_state_value >= current_state_value:
return current_state, current_state_value
current_state = best_successor_state
如果我对你的问题的理解正确,你是在问为什么 best_successor_state 值不会随着 for 循环的每次迭代而改变。
答案很简单,因为你就是这样写的(而且它应该适用于你的本地搜索)。
if successor_state_value < best_successor_state_value:
这一行确保 best_successor_state 仅在这种情况下分配给后继状态,即新状态实际上比您当前的最佳继任者更好。
记住这一点,为了回答你的第二个问题,你的代码已经在需要时更新了你最好的继任者。
我不明白你问题的第三部分。
我不完全明白你不明白的是什么。据我所知,这段代码是有效的(你已经明白了,但我的意思是你描述的行为与这段代码应该做的相匹配)。你说 "Since I am assigning(?) best_sucessor_state to the variable successor_state [...]" 我不知道这是否只是对语言的混淆,但它实际上是相反的:你将 successor_state
分配给变量 best_successor_state
这发生在每次迭代loop if 本次迭代的 successor_state_value
小于当前的 best_successor_state_value
如果您希望 best_successor_state
更新循环的每次迭代,您只需删除 if
语句,但这意味着在 for
-loop best_successor_state
将等于 current_state.successor_states()
中的最后一个值
正在为变量赋值。在 best_successor_state = successor_state
中,您将值 successor_state
分配给变量 best_successor_state
.
最简短的回答是 python 变量就像 C 指针(如果您熟悉 C),并且您的代码的执行完全符合预期。要详细了解您的问题:
当您在 python 中写入 x = 1
时,您是说变量 x
应该指向存储 [=12= 值的内存位].如果你然后写 y = x
你是说 y
应该指向存储 x
值的内存位,这是通过查看 [=11 指向的内存位来找到的=].出于所有意图和目的,这两个变量现在是相同的,修改一个的状态将修改另一个的状态。但是,如果您随后写了 x = 4
,那么您要求 x
指向存储 4
值的内存,而 y
仍然指向它的先前值 1
.
这会影响您的程序的方式是,当您编写 best_successor_state = successor_state
时,您要求 best_successor_state
指向 successor_state
的值,这是通过查看值 successor_state
指向。所以在这条语句之后,两个变量实际上是同一件事。然后,当您到达 for successor_state in current_state.successor_states():
时,您实际上是在调用 successor_state = <SOME_OTHER_STATE>
。现在 best_successor_state
指向 successor_state
曾经拥有的值,而 successor_state
指向新状态;再一次,它们不再是等效的对象。
您在这里要求的是 successor_state
和 best_successor_state
始终是同一个对象。我看到的唯一方法是用 for best_successor_state in current_state.successor_states():
.
之类的愚蠢的东西替换 for successor_state in current_state.successor_sates():
只要你有x = y
形式的东西,你就可以分配一个变量。每当您查看变量的值时,您就引用了一个变量,因此在 x = y
中,您引用的是 y
。变量用于表示您可以在程序中操作的值,我肯定会在标签或名称上使用它(您可能会说“x”是变量 x
的标签,但这有点像语义)。
Why this is the case?
发生这种情况是因为每次执行循环时,successor_state
都会成为 current_state.successor_states()
创建的不同对象的标签。当您随后分配 best_successor_state
时,您正在为该特定 successor_state
对象创建一个标签(即内存中 successor_state
指向的地址,而不是 successor_state
标签本身).如果你运行这段代码就会很清楚(id
给你对象的内存地址,至少在CPython中):
max_value = 0
for index in [1, 3, 2]:
print("Current index id: ", id(index))
if max_value < index:
max_value = index
print("Maximum index id: ", id(max_value))
当index
从3变为2时,max_value
一直指向index
的前一个id。它指向那个 id 而不是 "whatever index
points to at the moment".
If I wanted to break my code and have best_successor_state stay up to
date with the changes of successor_state as the loop loops, how could
I do this?
你可以做类似指向一个对象的事情:
class A:
pass
a = A()
m = a
for i in range(3):
a.x = i
print(m.x)
您会看到 m.x
从 a.x
获取值,即使我们没有直接更改它。
关于你的最后一个问题,它在这种情况下是相关的,因为它实际上是关于实体是标签而不是引用,但我不是那些更详细的专家,无法给你一个好的答案。
我有一些代码可以满足我的需要,但我希望它不会。我希望它应该被破坏,但它确实有效。
我一直在尝试从对象列表中查找并跟踪最佳*实例,并且每次我找到 successor_state
比当前的 best_sucessor_state
更好*。
在 for 循环的每个循环中,变量 successor_state
被分配(?)到 [=20= 生成的 state
对象列表中的新 state
实例]
因为我正在分配(?)best_sucessor_state
变量 successor_state
,我不明白为什么 best_successor_state
被分配到的基础状态(?)不更新每个时间 for-loop 循环和变量 successor state
被分配(?)到 current_state.successor_states()
列表中的新 state
。
如果有人能解释以下内容,我将不胜感激:
- 为什么会这样?
- 如果我想破坏我的代码并让
best_successor_state
跟上循环中successor_state
的变化,我该怎么做? - 我应该使用什么准确的语言("assignment/referencing"、"variable/label/name")?
*best:state
class有一个计算值的方法,叫做objective_function
,越低越好
这是代码,非常感谢:
def steepest_ascent_HCS(initial_state, objective_function):
current_state = initial_state
while True:
current_state_value = objective_function(current_state)
best_successor_state_value = float('inf')
for successor_state in current_state.successor_states():
successor_state_value = objective_function(successor_state)
if successor_state_value < best_successor_state_value:
best_successor_state = successor_state
best_successor_state_value = successor_state_value
if best_successor_state_value >= current_state_value:
return current_state, current_state_value
current_state = best_successor_state
如果我对你的问题的理解正确,你是在问为什么 best_successor_state 值不会随着 for 循环的每次迭代而改变。
答案很简单,因为你就是这样写的(而且它应该适用于你的本地搜索)。
if successor_state_value < best_successor_state_value:
这一行确保 best_successor_state 仅在这种情况下分配给后继状态,即新状态实际上比您当前的最佳继任者更好。
记住这一点,为了回答你的第二个问题,你的代码已经在需要时更新了你最好的继任者。
我不明白你问题的第三部分。
我不完全明白你不明白的是什么。据我所知,这段代码是有效的(你已经明白了,但我的意思是你描述的行为与这段代码应该做的相匹配)。你说 "Since I am assigning(?) best_sucessor_state to the variable successor_state [...]" 我不知道这是否只是对语言的混淆,但它实际上是相反的:你将
successor_state
分配给变量best_successor_state
这发生在每次迭代loop if 本次迭代的successor_state_value
小于当前的best_successor_state_value
如果您希望
best_successor_state
更新循环的每次迭代,您只需删除if
语句,但这意味着在for
-loopbest_successor_state
将等于current_state.successor_states()
中的最后一个值
正在为变量赋值。在
best_successor_state = successor_state
中,您将值successor_state
分配给变量best_successor_state
.
最简短的回答是 python 变量就像 C 指针(如果您熟悉 C),并且您的代码的执行完全符合预期。要详细了解您的问题:
当您在 python 中写入
x = 1
时,您是说变量x
应该指向存储 [=12= 值的内存位].如果你然后写y = x
你是说y
应该指向存储x
值的内存位,这是通过查看 [=11 指向的内存位来找到的=].出于所有意图和目的,这两个变量现在是相同的,修改一个的状态将修改另一个的状态。但是,如果您随后写了x = 4
,那么您要求x
指向存储4
值的内存,而y
仍然指向它的先前值1
.这会影响您的程序的方式是,当您编写
best_successor_state = successor_state
时,您要求best_successor_state
指向successor_state
的值,这是通过查看值successor_state
指向。所以在这条语句之后,两个变量实际上是同一件事。然后,当您到达for successor_state in current_state.successor_states():
时,您实际上是在调用successor_state = <SOME_OTHER_STATE>
。现在best_successor_state
指向successor_state
曾经拥有的值,而successor_state
指向新状态;再一次,它们不再是等效的对象。您在这里要求的是
之类的愚蠢的东西替换successor_state
和best_successor_state
始终是同一个对象。我看到的唯一方法是用for best_successor_state in current_state.successor_states():
.for successor_state in current_state.successor_sates():
只要你有
x = y
形式的东西,你就可以分配一个变量。每当您查看变量的值时,您就引用了一个变量,因此在x = y
中,您引用的是y
。变量用于表示您可以在程序中操作的值,我肯定会在标签或名称上使用它(您可能会说“x”是变量x
的标签,但这有点像语义)。
Why this is the case?
发生这种情况是因为每次执行循环时,successor_state
都会成为 current_state.successor_states()
创建的不同对象的标签。当您随后分配 best_successor_state
时,您正在为该特定 successor_state
对象创建一个标签(即内存中 successor_state
指向的地址,而不是 successor_state
标签本身).如果你运行这段代码就会很清楚(id
给你对象的内存地址,至少在CPython中):
max_value = 0
for index in [1, 3, 2]:
print("Current index id: ", id(index))
if max_value < index:
max_value = index
print("Maximum index id: ", id(max_value))
当index
从3变为2时,max_value
一直指向index
的前一个id。它指向那个 id 而不是 "whatever index
points to at the moment".
If I wanted to break my code and have best_successor_state stay up to date with the changes of successor_state as the loop loops, how could I do this?
你可以做类似指向一个对象的事情:
class A:
pass
a = A()
m = a
for i in range(3):
a.x = i
print(m.x)
您会看到 m.x
从 a.x
获取值,即使我们没有直接更改它。
关于你的最后一个问题,它在这种情况下是相关的,因为它实际上是关于实体是标签而不是引用,但我不是那些更详细的专家,无法给你一个好的答案。