Skip to main content
 首页 » 编程设计

python递归实例变量共享数据

2025年05月04日10jpfss

我正在尝试创建一个创建树的递归函数。每个节点都保存着一个井字游戏的状态,每个节点的子节点是下一个可能的走法。

我将棋盘的状态传递给递归函数。对于每一个可能的移动,我都会创建一个状态副本,然后进行移动。这个新状态被传递给递归函数。

#XXX 
#O O = state [1,1,1,-1,0,-1,1,1,1] 
#XXX 
 
playerX = 1 
playerO = -1 
 
class node: 
    children = [] #holds all the children 
    state = [] #holds the state of the board as a list of ints 
    def __init__(self,st): 
        self.state = st 
 
    def addChild(self,child): 
        self.children.append(child) #if only giving birth was this easy 
 
#returns a node with all it's children filled in 
#cState is the state for this node 
#currentPlayer flips sign every function call 
#stateSize is the size of the board 
def makeTreeXO(cState,currentPlayer,stateSize): 
    newNode = node(cState) 
    for i in range(stateSize): 
        print "looking at", i, "in", cState 
        if(cState[i] == 0): #found an open space 
            print "found an empty space" 
            newState = cState #create copy of state 
            newState[i] = currentPlayer #make the available move 
            print "made new state" 
            newNode.addChild(makeTreeXO(newState,currentPlayer*-1,stateSize)) 
    print "Done with this instance" 
    return newNode 
 
root = makeTreeXO([1,0,0,1,1,1,1,1,1],playerX,9) 

输出:

looking at 0 in [1, 0, 0, 1, 1, 1, 1, 1, 1] 
looking at 1 in [1, 0, 0, 1, 1, 1, 1, 1, 1] 
found an empty space 
made new state 
looking at 0 in [1, 1, 0, 1, 1, 1, 1, 1, 1] 
looking at 1 in [1, 1, 0, 1, 1, 1, 1, 1, 1] 
looking at 2 in [1, 1, 0, 1, 1, 1, 1, 1, 1] 
found an empty space 
made new state 
looking at 0 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 1 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 2 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 3 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 4 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 5 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 6 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 7 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 8 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
Done with this instance 
looking at 3 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 4 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 5 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 6 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 7 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 8 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
Done with this instance 
looking at 2 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 3 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 4 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 5 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 6 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 7 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
looking at 8 in [1, 1, -1, 1, 1, 1, 1, 1, 1] 
Done with this instance 

从 print 语句可以清楚地看出,对状态所做的更改正在返回到函数的父实例。有谁知道为什么吗?

请您参考如下方法:

问题是,您正在修改类变量,它们将由特定类的所有对象共享。要解决此问题,请像这样创建 state 和 children 实例变量

class node: 
    def __init__(self,st): 
        self.state = st 
        self.children = [] 
 
    def addChild(self,child): 
        self.children.append(child) #if only giving birth was this easy 

按照这一行,

newState = cState #create copy of state 

您正在尝试创建 cState 的副本并将其存储在 newState 中。请记住,在 Python 中,赋值运算符永远不会将一个值复制到另一个。它只是使左侧的变量指向赋值语句右侧表达式的求值结果。

因此,您实际上在做的是,使 newState 和 cState 都指向同一个列表。因此,如果您修改 newState,它也会影响 cState。要实际创建列表的副本,您可以使用切片运算符,如下所示

newState = cState[:] #create copy of state