循环遍历 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

如果有人能解释以下内容,我将不胜感激:

  1. 为什么会这样?
  2. 如果我想破坏我的代码并让 best_successor_state 跟上循环中 successor_state 的变化,我该怎么做?
  3. 我应该使用什么准确的语言("assignment/referencing"、"variable/label/name")?

*beststateclass有一个计算值的方法,叫做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 仅在这种情况下分配给后继状态,即新状态实际上比您当前的最佳继任者更好。
记住这一点,为了回答你的第二个问题,你的代码已经在需要时更新了你最好的继任者。 我不明白你问题的第三部分。

  1. 我不完全明白你不明白的是什么。据我所知,这段代码是有效的(你已经明白了,但我的意思是你描述的行为与这段代码应该做的相匹配)。你说 "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

  2. 如果您希望 best_successor_state 更新循环的每次迭代,您只需删除 if 语句,但这意味着在 for-loop best_successor_state 将等于 current_state.successor_states()

  3. 中的最后一个值
  4. 正在为变量赋值。在 best_successor_state = successor_state 中,您将值 successor_state 分配给变量 best_successor_state.

最简短的回答是 python 变量就像 C 指针(如果您熟悉 C),并且您的代码的执行完全符合预期。要详细了解您的问题:

  1. 当您在 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 指向新状态;再一次,它们不再是等效的对象。

  2. 您在这里要求的是 successor_statebest_successor_state 始终是同一个对象。我看到的唯一方法是用 for best_successor_state in current_state.successor_states():.

    之类的愚蠢的东西替换 for successor_state in current_state.successor_sates():
  3. 只要你有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.xa.x 获取值,即使我们没有直接更改它。

关于你的最后一个问题,它在这种情况下是相关的,因为它实际上是关于实体是标签而不是引用,但我不是那些更详细的专家,无法给你一个好的答案。