繁体   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