簡體   English   中英

遞歸函數中的Python命名空間

[英]Python Namespaces in Recursive Functions

與我到達那里相比,我的問題相對簡單。 Python中的遞歸函數每次函數調用自身時都會創建一個新的命名空間嗎?

我正在閱讀mergesort並閱讀本教程: https ://interactivepython.org/runestone/static/pythonds/SortSearch/TheMergeSort.html#lst-merge

def mergeSort(alist):
    print("Splitting ",alist)
    if len(alist)>1:
        mid = len(alist)//2
        lefthalf = alist[:mid]
        righthalf = alist[mid:]

        mergeSort(lefthalf)
        mergeSort(righthalf)

        i=0
        j=0
        k=0
        while i < len(lefthalf) and j < len(righthalf):
            if lefthalf[i] < righthalf[j]:
                alist[k]=lefthalf[i]
                i=i+1
            else:
                alist[k]=righthalf[j]
                j=j+1
            k=k+1

        while i < len(lefthalf):
            alist[k]=lefthalf[i]
            i=i+1
            k=k+1

        while j < len(righthalf):
            alist[k]=righthalf[j]
            j=j+1
            k=k+1
    print("Merging ",alist)

alist = [54,26,93,17,77,31,44,55,20]
mergeSort(alist)
print(alist)

我已經足夠了解分而治之,但我現在無法理解的是我上面提到的問題。 我可以遵循代碼,但我不太了解使用lefthalf作為傳遞給mergeSort的遞歸函數調用的參數。

我得到的是當mergeSort首先在底部調用時,alist被切入[54,26,93,17]和[17,27,31,44,55,20]。 這些是lefthalf和righthalf。 然后在lefthalf上調用mergeSort。 這是我感到困惑的地方。 對mergeSort的遞歸調用是否會創建一個全新的命名空間,這就是為什么傳入的lefthalf不會與函數中定義的lefthalf沖突的原因?

我知道答案是非常簡單和基本的,所以你的耐心非常感謝。 提前致謝!

是的,函數調用(任何函數調用,而不僅僅是遞歸調用)都會創建一個新的命名空間。 但是,當作為參數給出時,對象通過引用傳遞(在您的示例中,對象是列表)。

因此,新命名空間獲得它自己的引用副本,但它仍然引用與調用函數中相同的對象,如果更改該對象的內容,您將注意到調用函數的更改。

不確定我是否足夠清楚。 這是一個很好的圖表 ,可能有助於理解這是如何工作的。

對mergeSort的遞歸調用是否會創建一個全新的命名空間,[...]?

是。

只要解釋器​​遇到對函數的調用,它就會創建一個框架對象 ,並將其推送到框架堆棧 每次創建一個幀時,該幀都被賦予其自己的私有名稱空間,其中幀中的每個變量都被重新定義。

在您的情況下,每次調用mergeSort() ,Python都會創建一個新的框架對象,並將其推送到框架堆棧。 每次Python從調用mergeSort()創建一個幀時, lefthalf重新定義lefthalf

通過幾次調用print() ,您可以在每次調用mergeSort()看到lefthalf的值:

 This is the 1 recursive call to mergeSort()
 lefthalf is:  [54, 26, 93, 17]
 alist is:  [54, 26, 93, 17, 77, 31, 44, 55, 20]
  This is the 2 recursive call to mergeSort()
  lefthalf is:  [54, 26]
  alist is:  [54, 26, 93, 17]
   This is the 3 recursive call to mergeSort()
   lefthalf is:  [54]
   alist is:  [54, 26]
    This is the 4 recursive call to mergeSort()
     This is the 5 recursive call to mergeSort()
      This is the 6 recursive call to mergeSort()
      lefthalf is:  [93]
      alist is:  [93, 17]
       This is the 7 recursive call to mergeSort()
        This is the 8 recursive call to mergeSort()
         This is the 9 recursive call to mergeSort()
         lefthalf is:  [77, 31]
         alist is:  [77, 31, 44, 55, 20]
          This is the 10 recursive call to mergeSort()
          lefthalf is:  [77]
          alist is:  [77, 31]
           This is the 11 recursive call to mergeSort()
            This is the 12 recursive call to mergeSort()
             This is the 13 recursive call to mergeSort()
             lefthalf is:  [44]
             alist is:  [44, 55, 20]
              This is the 14 recursive call to mergeSort()
               This is the 15 recursive call to mergeSort()
               lefthalf is:  [55]
               alist is:  [55, 20]
                This is the 16 recursive call to mergeSort()
                 This is the 17 recursive call to mergeSort()
[17, 20, 26, 31, 44, 54, 55, 77, 93]
>>> 

暫無
暫無

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

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