Python 在变量内部完成的递归

Python 在变量内部完成的递归,python,recursion,stack-trace,Python,Recursion,Stack Trace,如果编译器在变量中,我对它如何进行递归感到有点困惑。唯一容易解释这个问题的方法是我举个例子 def recur_var(s1, s2): '''Test for recursion in variables.''' if s1 == '': return s2 elif s2 == '': return s1 else: test = recur_var(s1[:-1], s2[:-1]) if s1

如果编译器在变量中,我对它如何进行递归感到有点困惑。唯一容易解释这个问题的方法是我举个例子

def recur_var(s1, s2):
    '''Test for recursion in variables.'''
    if s1 == '':
        return s2
    elif s2 == '':
        return s1
    else:
        test = recur_var(s1[:-1], s2[:-1])
        if s1[-1] == '1' and s2[-1] == '1':
            return True 
        return test
在上述代码中,除了基本情况外,唯一的递归是在优先级高于所有其他情况的变量内部

我意识到这段代码在它的功能方面到处都是,但我的问题是,在这个堆栈的跟踪中,测试是否只会成为切片的剩余部分

test
是否在不检查
s1[-1]
s2[-1]
是否都是
1
的情况下,一直递归到基本情况?换句话说,它是在调用时100%忽略其下的所有内容,还是忽略自身并遵循代码的其余部分,然后调用


我意识到这可能被问到了,措辞也很糟糕,但我自己也很困惑,所以我不知道更好的方法。

每次调用
recurr\u var
时,您都会使用
创建新字符串。…[:-1]
。但是它们不会覆盖方法中已经存在的
s1
/
s2
变量。因此,下一行中的检查实际上是对传递给函数调用的原始值进行的

基本上,每次调用此函数时,它都会创建一组新的变量(因此在您的情况下,
s1
s2
test
)。例如:

def foo(x):
    x = x - 1
    if x > 0:
        foo(x)
    print(x)

foo(3)
这将输出2到0,每个调用都有自己的
x
。你可以把你想要的全部赋值给它们,它不会对其他函数调用中的变量做任何事情

例如,它首先调用
foo(3)
,然后将
x
减少1,并调用
foo(x)
,即
foo(2)
,在那里它将
x
再次减少1,但
foo(3)
的上下文中
x
仍然是2

现在例外情况是全局变量,如果您修改一个变量(执行
x=42
不会修改
x
,但会覆盖
x
)。

如果您将以下行

print("testing s1[-1] == '1' and s2[-1] == '1' with s1, s2 = " + s1 + ", " + s2)
在递归调用之后和
之前,如果s1[-1]=='1'和s2[-1]=='1':
,典型的输出是:

>>> recur_var('1001','1100')
testing s1[-1] == '1' and s2[-1] == '1' with s1, s2 = 1, 1
testing s1[-1] == '1' and s2[-1] == '1' with s1, s2 = 10, 11
testing s1[-1] == '1' and s2[-1] == '1' with s1, s2 = 100, 110
testing s1[-1] == '1' and s2[-1] == '1' with s1, s2 = 1001, 1100

因此,您只能在递归完成后测试顶级
s1、s2
(您在最后一行中看到的内容)。在递归的早期阶段,该测试运行,但使用较小的字符串,这些字符串是原始字符串的切片。

简短回答

是的,函数在检查结束字符之前会在缩短的字符串上递归。它只有在耗尽其中一个字符串后才进行检查——当它返回调用堆栈时


注意事项

  • 编译器生成机器代码;运行时系统或Python解释实际上执行递归
  • 变量内部没有递归。变量是数据;递归是一个控制流概念。我不太清楚你的用法是什么意思
  • 此外,您还没有描述您的日常工作应该做什么。它实际做的是找出字符“1”是否出现在两个给定字符串末尾的相同距离处。如果是,则返回True;否则,它将返回较长字符串的第一个(abs(len(s1)-len(s2))字符


    跟踪您的执行情况

    学习一些。当你继续编程时,它们会很好地为你服务

    为了完成你的计划,我做了两件事:

  • 我将其转换为结构化编程:例程的一个出口。我将所需的结果放入变量中,并且只在例程的底部返回。这允许我在单个出口点跟踪执行情况
  • 这看起来像:

    def recur_var(s1, s2):
        global depth
        '''Test for recursion in variables.'''
        if s1 == '':
            result = s2
        elif s2 == '':
            result = s1
        else:
            test = recur_var(s1[:-1], s2[:-1])
            if s1[-1] == '1' and s2[-1] == '1':
                result = True 
            else:
                result = test
    
        return result
    
    depth = 0
    def recur_var(s1, s2):
        global depth
        depth += 1
        print "  "* depth, "ENTER", "s1 =", s1, "s2 =", s2
        '''Test for recursion in variables.'''
        if s1 == '':
            print "  "* depth, "s1 is empty; return s2"
            result = s2
        elif s2 == '':
            print "  "* depth, "s2 is empty; return s1"
            result = s1
        else:
            test = recur_var(s1[:-1], s2[:-1])
            print "  "* depth, "both strings have chars; test=", test
            if s1[-1] == '1' and s2[-1] == '1':
                result = True 
            else:
                result = test
    
        print "  "* depth, "LEAVE", "result =", result
        depth -= 1
        return result
    
    print recur_var("8610", "17")
    print recur_var("X8610", "X17")
    print recur_var("hello", "world !")
    
  • 接下来,我插入了调试跟踪:打印语句以跟踪条目和返回,以及缩进计数器以使事情更易于可视化
  • 这看起来像:

    def recur_var(s1, s2):
        global depth
        '''Test for recursion in variables.'''
        if s1 == '':
            result = s2
        elif s2 == '':
            result = s1
        else:
            test = recur_var(s1[:-1], s2[:-1])
            if s1[-1] == '1' and s2[-1] == '1':
                result = True 
            else:
                result = test
    
        return result
    
    depth = 0
    def recur_var(s1, s2):
        global depth
        depth += 1
        print "  "* depth, "ENTER", "s1 =", s1, "s2 =", s2
        '''Test for recursion in variables.'''
        if s1 == '':
            print "  "* depth, "s1 is empty; return s2"
            result = s2
        elif s2 == '':
            print "  "* depth, "s2 is empty; return s1"
            result = s1
        else:
            test = recur_var(s1[:-1], s2[:-1])
            print "  "* depth, "both strings have chars; test=", test
            if s1[-1] == '1' and s2[-1] == '1':
                result = True 
            else:
                result = test
    
        print "  "* depth, "LEAVE", "result =", result
        depth -= 1
        return result
    
    print recur_var("8610", "17")
    print recur_var("X8610", "X17")
    print recur_var("hello", "world !")
    
    …这些测试的输出是

       ENTER s1 = 8610 s2 = 17
         ENTER s1 = 861 s2 = 1
           ENTER s1 = 86 s2 = 
           LEAVE result = 86
         LEAVE result = True
       LEAVE result = True
    True
       ENTER s1 = X8610 s2 = X17
         ENTER s1 = X861 s2 = X1
           ENTER s1 = X86 s2 = X
             ENTER s1 = X8 s2 = 
             LEAVE result = X8
           LEAVE result = X8
         LEAVE result = True
       LEAVE result = True
    True
       ENTER s1 = hello s2 = world !
         ENTER s1 = hell s2 = world 
           ENTER s1 = hel s2 = world
             ENTER s1 = he s2 = worl
               ENTER s1 = h s2 = wor
                 ENTER s1 =  s2 = wo
                 LEAVE result = wo
               LEAVE result = wo
             LEAVE result = wo
           LEAVE result = wo
         LEAVE result = wo
       LEAVE result = wo
    wo
    

    这应该能让你了解你需要知道的一切。

    谢谢,但我想我应该说到点子上了,我问这个问题是想看看我是否能理解以下函数的工作原理,但我还是很不确定。当ab('111','111')时,sumhead_ab不是总是变成''吗被调用?它做的加法正确,我只是不知道sumhead_ab如何在需要时进行1的结转。我仍然不知道这个网站是如何工作的,所以我尝试将代码作为编辑放在线程中…我不知道你想说什么,因为sumhead_ab和ab没有出现在你的代码中。我担心你说什么“我仍然不知道这个网站是如何工作的”。你需要帮助编辑标记(格式)吗?当您编辑时,可以在链接中找到这些内容。您是否参加过介绍性教程?此添加内容似乎是一个单独的问题。如果是,请发布一个新问题。如果不是,请解释两者是如何链接的。在任何情况下,请使用此添加的代码解释问题。欢迎使用StackOverflow。请阅读并遵循帖子帮助文档中的ng指南。适用于此处。在您发布完整的代码并准确描述问题之前,我们无法有效地帮助您。好吧,很抱歉,作为一个noob,我本应该参加您所说的教程。我的问题是,我不太理解编辑的代码是如何工作的,它与问题相关,因为它是递归的ion被添加到未更改的字符串中,所以我不知道这个函数是如何工作的。我认为s1和s2永远不会改变,只是与基本情况相同。是的,你应该在发布之前进行浏览!你还应该应用BKM(最著名的方法)在你寻求帮助之前——这更多的是为了你自己的教育,而不是为了我们的利益。当你将我的跟踪建议应用到编辑过的代码中时,你得到了什么?你在理解这些代码时遇到了什么困难