简体   繁体   English

Python 在递归代码中返回另一个 function --> 它是如何工作的?

[英]Python return another function in recursive code-->how is it work?

I'm studying merge sort using python and I can't understand this code example.我正在使用 python 研究合并排序,但我无法理解此代码示例。

''' '''

def merge(left, right):
    merged = list()
    left_point, right_point = 0, 0

    # case1 - left/right 둘다 있을때
    while len(left) > left_point and len(right) > right_point:
        if left[left_point] > right[right_point]:
            merged.append(right[right_point])
            right_point += 1
        else:
            merged.append(left[left_point])
            left_point += 1

    # case2 - left 데이터가 없을 때
    while len(left) > left_point:
        merged.append(left[left_point])
        left_point += 1

    # case3 - right 데이터가 없을 때
    while len(right) > right_point:
        merged.append(right[right_point])
        right_point += 1

    return merged


def mergesplit(data):
    if len(data) <= 1:
        return data
    medium = int(len(data) / 2)
    left = mergesplit(data[:medium])
    right = mergesplit(data[medium:])
    return merge(left, right)

''' Let's say I have an array [6,2,3,9,5,7] ''' 假设我有一个数组 [6,2,3,9,5,7]

Then it'll be split to a half size and it will call merge(left,right) if the len(data) is larger than 1.然后它将被拆分为一半大小,如果 len(data) 大于 1,它将调用 merge(left,right)。

BUT the thing is, isn't a stack is destroyed if you call return merge(left, right)?但问题是,如果调用 return merge(left,right),堆栈不会被破坏吗? So how can you apply recursive here when the function returns another function?那么当 function 返回另一个 function 时,如何在这里应用递归呢? Also, merge(left, right) function return 'merged', but there's no list variable that can held merged(eg receive_list=merge(left,right)) so how can we receive merge?此外,merge(left,right) function 返回“merged”,但是没有可以合并的列表变量(例如,receive_list=merge(left,right))那么我们如何接收合并?

I've always used java so it't my first time using python我一直使用 java 所以这不是我第一次使用 python

Maybe there are some principle of python I'm missing?也许我缺少一些 python 的原理?

Thanks in advance!提前致谢!

Perhaps this helps.也许这会有所帮助。

To sort array arr对数组 arr 进行排序

We split arr in half, and call mergesplit on the left and right halves我们把arr一分为二,左右两半分别调用mergesplit

left = mergesplit(data[:medium])
right = mergesplit(data[medium:])

Each of these mergesplit calls splits its array into left and right halves and calls mergesplit on each of these (ie left child and right child).这些mergesplit 调用中的每一个都将其数组拆分为左右两半,并在其中的每一个上调用mergesplit(即左孩子和右孩子)。

This can be visualized as a call tree with each parent node having two children (left & right).这可以可视化为一个调用树,每个父节点都有两个子节点(左和右)。

The successive calls of mergesplit continues until the base case: mergesplit 的连续调用一直持续到基本情况:

if len(data) <= 1:
    return data

This returns its data (single value) to its parent.这会将其数据(单个值)返回给其父级。

The parent has left and right (each a single value).父级有左和右(每个都有一个值)。

It returns merge of these two values (left, right) to its parent:它将这两个值(左、右)的合并返回给它的父级:

 return merge(left, right)

So to answer your basic question about who receives the return of merge, we see that it goes to the parent.因此,为了回答您关于谁收到合并返回的基本问题,我们看到它转到了父级。

The higher parent has a left, right (two values) each, so an array with four elements total.较高的父级各有一个左、右(两个值),因此是一个总共有四个元素的数组。

Each parent in the call tree calls merge on the right and left that it receives from its child returning the merge result to its parent.调用树中的每个父级调用它从其子级接收的左右合并,将合并结果返回给其父级。

This unwinds back up the tree until we get to the top node that returns the result of the merge to the original caller.这将展开树,直到我们到达将合并结果返回给原始调用者的顶部节点。

Add Showing of Stack添加堆栈显示

import sys
import inspect

def merge(left, right):
    show_info('merge')
    merged = list()
    left_point, right_point = 0, 0

    # case1 - left/right 둘다 있을때
    while len(left) > left_point and len(right) > right_point:
        if left[left_point] > right[right_point]:
            merged.append(right[right_point])
            right_point += 1
        else:
            merged.append(left[left_point])
            left_point += 1

    # case2 - left 데이터가 없을 때
    while len(left) > left_point:
        merged.append(left[left_point])
        left_point += 1

    # case3 - right 데이터가 없을 때
    while len(right) > right_point:
        merged.append(right[right_point])
        right_point += 1

    return merged

def mergesplit(data):
    show_info('mergesplit:')
    if len(data) <= 1:
        return data
    medium = int(len(data) / 2)
    left = mergesplit(data[:medium])
    right = mergesplit(data[medium:])
    return merge(left, right)

def show_info(message):
  " Shows locals and stack trace "
  previous_frame = sys._getframe(1)
  previous_frame_locals = previous_frame.f_locals

  # Stack Depth of caller
  depth = len(inspect.stack(0)) - 3 # 3 things to start so offset
  offset = depth*2

  print('\t'*offset + message, "\n" + '\t'*offset, previous_frame_locals)

mergesplit([4, 3, 2, 1])

Example例子

mergesplit([4, 3, 2, 1])

Output Output

This results the stack as mergesplit and merge are called illustrating the recursive nature of the calls.这导致堆栈作为 mergesplit 和 merge 被调用,说明了调用的递归性质。

mergesplit: 
 {'data': [4, 3, 2, 1]}
        mergesplit: 
         {'data': [4, 3]}
                mergesplit: 
                 {'data': [4]}
                mergesplit: 
                 {'data': [3]}
                merge 
                 {'left': [4], 'right': [3]}
        mergesplit: 
         {'data': [2, 1]}
                mergesplit: 
                 {'data': [2]}
                mergesplit: 
                 {'data': [1]}
                merge 
                 {'left': [2], 'right': [1]}
        merge 
         {'left': [3, 4], 'right': [1, 2]}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM