簡體   English   中英

class 中的遞歸 function 調用似乎返回多個“自我”屬性?

[英]Recursive function calls inside class seem to return multiple 'self' attributes?

我正在嘗試創建一段代碼,該代碼可以以不同的方式打印出鏈接列表,具體取決於它的調用方式以及您選擇從列表中的哪個位置開始。

為此,我選擇了一個遞歸 function,您在初始調用中將數據傳遞給它,然后它通過遞歸調用傳遞該數據和更多內容,以構建所需的 output 形式。 但是,當我嘗試遞歸調用 function 時,“self”參數似乎發送了兩次,將自身寫入 function 中的前兩個 arguments。

class LinkedList(object):

def __init__(self):
    self.head = Node()
    self.allNodeLocations = {}

def buildLinkedList(self, curNode, finish=99999, between=False, location=[0, 0], allNodeLocations={}, i=0):
    def __init__(self, name):
        self.curNode = curNode
        self.finish = finish
        self.between = between
        self.location = location
        self.allNodeLocations = allNodeLocations
        self.i = i

    if len(curNode.getChildren()) > 1:
            for child in curNode.getChildren():
                location, allNodeLocations, i = self.buildLinkedList(self, child, finish, between, 
                         location, allNodeLocations, i) #THIS IS WHERE THE CODE FAILS
            location[0] -= 1
            i -= 1
    return location, allNodeLocations, i

在上述情況下,“child”變量應該是節點 object。 運行上面的腳本會給出“TypeError:buildLinkedList() 從 2 到 7 個位置 arguments 但給出了 8 個”

相反,如果我用該行調用 function

    self.buildLinkedList(self, child)

And check the values with pycharm debugger, both self, and the curNode (ie the child variable) both point to the same LinkedList object and the next variable in the function definition heading 'finish' contains the node object that child passed to the function that應改為在 curNode 變量下輸入。

請注意,我已刪除大量代碼以使其更易於閱讀,如果需要,其余代碼如下。 我很抱歉目前有大量無用的代碼,我打算將來用它做一些事情......

class Node(object):

    def __init__(self, busNum = None, data=None, children=None, parents=None):
        self.busNum = busNum
        self.data = data
        self.children = []
        self.parents = []
        if children:
            self.children += children
        if parents:
            self.parents += parents

    def getChildren(self):
        return self.children

    def getParents(self):
        return self.parents

    def setChild(self, child):
        self.children.append(child)

    def setParent(self, parent):
        self.children.append(parent)

    def getData(self):
        return self.data

    def setData(self, data):
        self.data = data

    def toString(self):
        return "Bus Number: " + str(self.busNum) + ", Data: " + str(self.data)


class LinkedList(object):

    def __init__(self):
        self.head = Node()
        self.allNodeLocations = {}
        # self.curLocation = [0, 0]

    def addBus(self, bus, data, children, parents):
        newNode = Node(bus, data, children, parents)

    def buildLinkedList(self, curNode, finish=99999, between=False, location=[0, 0], allNodeLocations={}, i=0):
        def __init__(self, name):
            self.curNode = curNode
            self.finish = finish
            self.between = between
            self.location = location
            self.allNodeLocations = allNodeLocations
            self.i = i

        allNodeLocations[curNode] = location
        if i >= finish:
            return allNodeLocations

        if len(curNode.getChildren()) == 0:
                # If there are no children, set the location of the current bus, and go down a y level
            # location[0] -= 1
            location[1] += 1
            # i -= 1
            # curNode = prevNode
            return location, allNodeLocations, i
        elif len(curNode.getChildren()) == 1:
                # If there is 1 child, set its location and move onto its next child, once we return from there,
                # subtract 1 from the current iteration and x location
            location[0] =+ 1
            i =+ 1
            if i > finish:
                i -= 1
                return location, allNodeLocations, i
            # prevNode = curNode
            curNode = curNode.getChildren()[0]
            location, allNodeLocations, i = self.buildLinkedList(self, curNode, finish, between, location, allNodeLocations, i)
            location[0] -= 1
            i -= 1
            return location, allNodeLocations, i
        elif len(curNode.getChildren()) > 1:
                i += 1
                location[0] += 1
                for child in curNode.getChildren():
                    location, allNodeLocations, i = self.buildLinkedList(self, child, between=False)#, finish, between, location, allNodeLocations, i)
                location[0] -= 1
                i -= 1
        return allNodeLocations

e=Node(4,11)
f=Node(5,11)
g=Node(6,11)
h=Node(8,11)
j=Node(10,11)
k=Node(11,11)
i=Node(7,33,[h])
d=Node(9,66,[j,k])
c=Node(3,66,[i])
b=Node(2,132,[e,f,g])
a=Node(1,66,[b,c])

listOfNodes = [a,b,c,d,e,f,g,h,i,j,k]

print(d.getChildren())
# d.setChild(11)
# g.setChild(9)
# i.setParent(4)
# print(d.getChildren())

linkd=LinkedList()
linkd.buildLinkedList(a)

--Update-- 用戶 Moxy 指出了該問題,修復方法是在 buildLinkedList 調用中刪除對 self 的調用。

順便說一句,當我運行腳本時,它會在每次迭代中創建一個帶有“位置”變量的字典,但是,每當位置變量更新時,它都會更新字典中它的所有實例。

為了澄清,我用“allNodeLocations [curNode] = location”行遞歸地制作字典,每次遞歸調用都會更新curNode和location變量,但是當位置發生變化時,它會立即將字典更新為每個相同的值字典中的單元格。

有沒有辦法只獲取位置變量的值而不是指針(如果這就是問題所在)?

當您調用buildLinkedList刪除self 它代表 class 的實例,因此當您在 class 中創建 function 時添加它,但在調用它時從不添加。 如果添加self ,它會在buildLinkedList的參數中創建一個偏移量。

試試這個:

self.buildLinkedList(curNode, finish, between, location, allNodeLocations, i)

修復此問題后,您將擁有一個

ValueError: too many values to unpack (expected 3)

要修復它,將buildLinkedList的最后return替換為:

return None, allNodeLocations, None

- 更新 -

這個更新問題是因為列表是通過引用而不是值傳遞的,修復它嘗試:

allNodeLocations[curNode] = location by allNodeLocations[curNode] = list(location)

或者

allNodeLocations[curNode] = location by allNodeLocations[curNode] = location[:]

順便說一句,我不明白你通過獲取位置值而不是指針的意思

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM