如何在这个(简单的)python过程中正确使用递归?

如何在这个(简单的)python过程中正确使用递归?,python,data-structures,recursion,Python,Data Structures,Recursion,伙计们,我写了一个函数来测试两个输入a和b是否具有相同的数据结构,方法如下: print same_structure([1, 0, 1], [a, b, c]) #>>> True #print same_structure([1, [0], 1], [2, 5, 3]) >>> False #print same_structure([1, [2, [3, [4, 5]]]], ['a', ['b', ['c', ['d', 'e']]]]) >&g

伙计们,我写了一个函数来测试两个输入a和b是否具有相同的数据结构,方法如下:

print same_structure([1, 0, 1], [a, b, c])
#>>> True
#print same_structure([1, [0], 1], [2, 5, 3])
>>> False
#print same_structure([1, [2, [3, [4, 5]]]], ['a', ['b', ['c', ['d', 'e']]]])
>>> True  
#print same_structure([1, [2, [3, [4, 5]]]], ['a', ['b', ['c', ['de']]]])
>>> False
这个函数在我的实现中使用递归。我是递归的初学者,递归思维仍然有困难。此外,为了避免欺骗答案,我想使用我自己的凌乱代码,并通过它学习使用以下代码行的递归调用:“相同的_结构返回a[I],b[e]”。有人能在下面的代码中演示如何正确使用递归吗? 提前感谢您的帮助

def is_list(p):
return isinstance(p, list)

def same_structure(a,b):
    if not is_list(a) and not is_list(b):
        print '#1'
        return True
    else:
        if is_list(a) and is_list(b):
            print '#2'
            if len(a) != len(b):
                print '#3'
                return False
            if len(a) == len(b):
                print '#4'
                for e in range(len(a)):
                    print 'e = ', e, 'a[e]= ', a[e], 'b[e]=', b[e]
                    return same_structure(a[e], b[e])           
        else:
            return False
以下工作:

def same_structure(a, b):
    if isinstance(a, list) and isinstance(b, list) and len(a) == len(b):
        return all(same_structure(A, B) for A, B in zip(a, b))
    return (not isinstance(a, list) and not isinstance(b, list))
编写递归函数时,首先需要考虑基本情况,即只返回一个值,而不调用任何递归。这里的基本情况是以下条件之一:

a是列表,b不是,反之亦然:返回False a和b都是列表,但长度不同:返回False a或b都不是列表:返回True 如果a和b都是列表,并且它们具有相同的长度,那么我们现在需要递归地检查这些列表的每个元素。zipa,b提供了一种方便的方法,可以一起迭代每个列表中的元素,如果任意两个子元素的相同_结构的结果为False,我们希望整个函数返回False。这就是使用all的原因,如果您不熟悉all,则它与以下循环等效,但效率更高:

match = True
for A, B in zip(a, b):
    if not same_structure(A, B):
        match = False
        break
return match
下面是如何在不做太多更改的情况下重写函数,其逻辑实际上与我的解决方案非常相似,但就在您过早从该循环返回的打印“4”下方:

def same_structure(a,b):
    if not is_list(a) and not is_list(b):
        print '#1'
        return True
    else:
        if is_list(a) and is_list(b):
            print '#2'
            if len(a) != len(b):
                print '#3'
                return False
            if len(a) == len(b):
                print '#4'
                for e in range(len(a)):
                    print 'e = ', e, 'a[e]= ', a[e], 'b[e]=', b[e]
                    if not same_structure(a[e], b[e]):
                        return False
                return True        
        else:
            return False
以下工作:

def same_structure(a, b):
    if isinstance(a, list) and isinstance(b, list) and len(a) == len(b):
        return all(same_structure(A, B) for A, B in zip(a, b))
    return (not isinstance(a, list) and not isinstance(b, list))
编写递归函数时,首先需要考虑基本情况,即只返回一个值,而不调用任何递归。这里的基本情况是以下条件之一:

a是列表,b不是,反之亦然:返回False a和b都是列表,但长度不同:返回False a或b都不是列表:返回True 如果a和b都是列表,并且它们具有相同的长度,那么我们现在需要递归地检查这些列表的每个元素。zipa,b提供了一种方便的方法,可以一起迭代每个列表中的元素,如果任意两个子元素的相同_结构的结果为False,我们希望整个函数返回False。这就是使用all的原因,如果您不熟悉all,则它与以下循环等效,但效率更高:

match = True
for A, B in zip(a, b):
    if not same_structure(A, B):
        match = False
        break
return match
下面是如何在不做太多更改的情况下重写函数,其逻辑实际上与我的解决方案非常相似,但就在您过早从该循环返回的打印“4”下方:

def same_structure(a,b):
    if not is_list(a) and not is_list(b):
        print '#1'
        return True
    else:
        if is_list(a) and is_list(b):
            print '#2'
            if len(a) != len(b):
                print '#3'
                return False
            if len(a) == len(b):
                print '#4'
                for e in range(len(a)):
                    print 'e = ', e, 'a[e]= ', a[e], 'b[e]=', b[e]
                    if not same_structure(a[e], b[e]):
                        return False
                return True        
        else:
            return False

您只执行第一个递归调用,因为您将立即返回


如果我理解您想要做什么,您需要调用与子元素相同的_结构,并检查它的返回值,而不是立即返回它。如果任何调用的结果为false,则返回false,否则返回true。

您只执行第一个递归调用,因为您将立即返回


如果我理解您想要做什么,您需要调用与子元素相同的_结构,并检查它的返回值,而不是立即返回它。如果任何调用的结果为false,则返回false,否则返回true。

尝试此解决方案,它适用于所有示例,并且以递归函数式编程风格编写,但不使用zip、all等。在每个步骤中,仅使用片段来减少列表的大小:

def same_structure(a, b):
    if a == [] or b == []:
        return a == b
    elif is_list(a[0]) != is_list(b[0]):
        return False
    elif not is_list(a[0]):
        return same_structure(a[1:], b[1:])
    else:
        return same_structure(a[0], b[0]) and same_structure(a[1:], b[1:])

尝试此解决方案,它适用于您的所有示例,并以递归、函数式编程风格编写,但不使用zip、all等。在每个步骤中,仅使用片段来减少列表的大小:

def same_structure(a, b):
    if a == [] or b == []:
        return a == b
    elif is_list(a[0]) != is_list(b[0]):
        return False
    elif not is_list(a[0]):
        return same_structure(a[1:], b[1:])
    else:
        return same_structure(a[0], b[0]) and same_structure(a[1:], b[1:])

嗨,@F.J!你的代码比我的好得多谢谢!。但我不想在这个硬件中使用zip或all。此外,为了避免欺骗答案,我想用我自己的凌乱代码,通过它,学习如何使用递归调用修复代码行“相同的_结构返回a[I],b[e]”。@Pythonista'sApprentice我在大约10分钟前做了一次编辑,其中有一个编辑版本的函数应该可以工作,但仍然遵循这些要求。嗨,@F.J!你的代码比我的好得多谢谢!。但我不想在这个硬件中使用zip或all。此外,为了避免欺骗答案,我想用我自己的凌乱代码,通过它,学习如何使用递归调用修复代码行“相同的_结构返回a[I],b[e]”。@Pythonista'sApprentice我在大约10分钟前做了一次编辑,其中有一个编辑版本的函数应该可以工作,同时仍然遵循这些要求。