【问题标题】:Functions change values in list even though list is not passed to functions即使列表未传递给函数,函数也会更改列表中的值
【发布时间】:2015-04-24 19:34:27
【问题描述】:

我正在尝试实施 I.A.类似广度优先搜索的算法来解决水壶问题,但我遇到了这个问题:

每次我向数组中添加一个新元素时,它都会将数组中的所有元素都更改为它。

换句话说……

“frontier”数组在每个“jug”函数调用之间改变其中的所有元素。

有人可以分享一些关于这段代码的见解吗?

(我比较担心实现逻辑,所以没有优化)

代码:

J1SIZE = 3
J2SIZE = 4

frontier = []
explored = []


def IsEmpty(array):
    result = False
    if len(array) == 0:
        result = True
    return result


#Fill up a jug
def fillJug(tempNode, jug):
    copyNode = tempNode
    copyNode = copyNode
    if jug == 1:
        copyNode[0] = J1SIZE
    elif jug == 2:
        copyNode[1] = J2SIZE
    print(copyNode)
    return copyNode

#Empty a jug
def emptyJug(tempNode, jug):
    copyNode = tempNode
    if jug == 1:
        copyNode[0] = 0
    elif jug == 2:
        copyNode[1] = 0
    print(copyNode)
    return copyNode

#Pass the content of a jug to another
def passJug(tempNode, jug):
    copyNode = tempNode
    if jug == 1:
        copyNode[1] = copyNode.j1
        copyNode[0] = 0
        if copyNode[1] > J2SIZE:
            copyNode[1] = J2SIZE
    elif jug == 2:
        copyNode[0] = copyNode[1]
        copyNode[1] = 0
        if copyNode[0] > J1SIZE:
            copyNode[0] = J1SIZE
    print(copyNode)
    return copyNode

#Check if solution was found
def goalTest(goalNode,currentNode):
    result = False
    if goalNode == currentNode:
        result = True
    return result

def BFS(start,end,frontier,explored):

    start_node = start
    frontier = [start_node] + frontier

    if goalTest(end,(frontier[0])):
        print('Solution:', frontier[0])
        exit()

    #Loop start
    while IsEmpty(frontier) == False:

        tempNode = frontier.pop(0)

        #Generate nodes (states)
        if tempNode[0] < J1SIZE:
            newNode = fillJug(tempNode, 1)
            if newNode not in explored:
                frontier = [newNode] + frontier
                print('Frontier1: ', frontier)

        if tempNode[1] < J2SIZE:
            newNode = fillJug(tempNode, 2)
            if newNode not in explored:
                frontier = [newNode] + frontier
                print('Frontier2: ', frontier)

        if tempNode[0] == J1SIZE:
            newNode = emptyJug(tempNode, 1)
            if newNode not in explored:
                frontier = [newNode] + frontier
                print('Frontier3: ', frontier)

        if tempNode[1] == J2SIZE:
            newNode = emptyJug(tempNode, 2)
            if newNode not in explored:
                frontier = [newNode] + frontier
                print('Frontier4: ', frontier)

        if (tempNode[0] > 0) and (tempNode[1] < J2SIZE):
            newNode = passJug(tempNode, 1)
            if newNode not in explored:
                frontier = [newNode] + frontier
                print('Frontier5: ', frontier)

        if (tempNode[1] > 0) and (tempNode[0] < J1SIZE):
            new_node = passJug(tempNode, 2)
            if new_node not in explored:
                frontier = [new_node] + frontier
                print('Frontier6: ', frontier)

        print('Frontier: ', frontier)
        print('Explored: ', explored)

        for node in frontier:
            if goalTest(end, node):
                print('Solution:', frontier[0])
                exit()
            if node not in explored:
                explored = [node] + explored

BFS([0,0],[0,2],frontier,explored)

固定代码:

http://codepaste.net/auun4u

【问题讨论】:

  • 是“每次我向数组中添加一个新元素时,它都会将数组中的所有元素更改为像它一样。”你的问题的描述?这不是所谓的语法问题。
  • 感谢您的反馈!我会尝试更清楚一点:“前沿”数组在每个“水罐”函数调用之间更改其中的所有元素。
  • 我冒昧地稍微改变了你的问题。 “语法错误”是编译器告诉您“第 33 行缺少‘;’”。有些人在 StackOverflow 上询问当这些发生时该怎么办。您的问题显然不是语法错误,但我担心这样称呼它会导致人们误解您的问题,并可能将其关闭为不清楚或缺乏努力。

标签: python python-3.x artificial-intelligence breadth-first-search water-jug-problem


【解决方案1】:

我制作了一个更小的代码示例来重现您的错误:

J1SIZE = 3
J2SIZE = 4


def fillJug(tempNode, jug):
    copyNode = tempNode
    copyNode = copyNode
    if jug == 1:
        copyNode[0] = J1SIZE
    elif jug == 2:
        copyNode[1] = J2SIZE
    return copyNode


frontier = [[0, 0]]
tempNode = frontier.pop(0)

newNode = fillJug(tempNode, 1)
frontier = [newNode] + frontier  # (1)

newNode = fillJug(tempNode, 2)  # (2)
frontier = [newNode] + frontier

问题在于,在我标记为(1) 的行中,您将newNode 设置为与tempNode 相同的对象作为frontier 中的第一项。然后,在我标记为(2) 的行中,您正在更改tempNode -- 在fillJug 内。所以frontier 中的值发生了变化。具体来说,您让copyNode 引用与tempNode 相同的对象,然后您正在更改copyNode(和tempNode)引用的数据。

您应该将copyNode 重新定义为

copyNode = tempNode[:]

这将导致copyNodetempNode 引用内存中的不同对象(具有相同的值)。 (另一种选择是在导入copy 之后将copyNode 设置为copy.copy(tempNode)。)

所以新的fillJug 将是

def fillJug(tempNode, jug):
    copyNode = tempNode[:]
    if jug == 1:
        copyNode[0] = J1SIZE
    elif jug == 2:
        copyNode[1] = J2SIZE
    return copyNode

同样的修复适用于其他 Jug 函数。

【讨论】:

  • 感谢您的关注和所有信息!它工作得很轻!现在我将专注于根据本书修复逻辑! ;D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
  • 1970-01-01
  • 1970-01-01
  • 2016-06-09
  • 2016-03-11
相关资源
最近更新 更多