为什么这个函数适用于min,但不是没有?

时间:2017-04-04 03:26:57

标签: python recursion min

def edDistRecursive(a,b):
    #print(a, 'a')
    #print(b,'b')

    if len(a) == 0:
        return len(b)

    if len(b)==0:
        return len(a)



    delta = 1 if a[-1] != b[-1] else 0
    return min(edDistRecursive(a[:-1], b[:-1]) + delta,   edDistRecursive(a[:-1], b)+1,  edDistRecursive(a, b[:-1]) +1)

edDistRecursive('actor','racto')

2

但是,如果我在没有min的情况下运行它,

TypeError: can only concatenate tuple (not "int") to tuple

这是一种用于遗传学(近似匹配)的算法,用于确定匹配ab所需的编辑次数。我想如果我毫不费力地运行它,我将能够看到每个函数产生了多少次编辑。

编辑:我想我理解输出是一个元组,但我也有点困惑。
如果我删除其他两个函数就是简化这个函数

def edDistRecursive(a,b):
    #print(a, 'a')
    #print(b,'b')

    if len(a) == 0:
        return len(b)

    if len(b)==0:
        return len(a)



    delta = 1 if a[-1] != b[-1] else 0
    return edDistRecursive(a[:-1], b[:-1]) + delta 


edDistRecursive('actor','racto')  returns a value of  5.

为什么在这里添加delta可以没有任何问题?

另一个例子如下:

def sum(x,y):
    x =3
    y =2

    return x+y, y


(sum(2,3))

即使像这样,其输出是一个元组,对它的一个元素的加法运算也没有问题。

在我上面的函数中,值delta或者+1被添加到元组中,这就是提出错误的内容,但似乎但是int值没有被添加到整个元组中。实际上每个元素都是元组由(function + int)组成。所以当元组本身的一个元素是(function + int)时,我看不到我是如何添加元组的。

x,y,z = edDistRecursive('actor','racto')似乎也导致同样的错误。

我认为通过为每个函数添加括号((edDistRecursive(a[:-1], b[:-1]) + delta), (edDistRecursive(a[:-1], b)+1), (edDistRecursive(a, b[:-1]) +1))

Python将能够将元组的每个元素视为function + int,但我遇到了同样的错误。

有没有办法获得每个函数的值,这是我最初的目标?

3 个答案:

答案 0 :(得分:4)

如果你考虑在递归的第二到最低(见下面的编辑)级别发生了什么,递归调用,例如edDistRecursive(a[:-1], b[:-1])将返回一个int元组。当程序尝试将delta值(这是一个int)连接到此元组时,会抛出错误。通过使用min,您可以保证返回类型始终相同并与您的实现兼容。

编辑:让我们逐步介绍一个示例,以便我们可以更直接地查看正在发生的事情。对于此示例,让我们使用min,以便我们可以看到问题出现的位置。

为了使示例简单,假设我们以

开头
edDistRecursive(['x','k','z'], ['y','e','d'])

在执行递归调用的某个时刻(即在每个return语句中执行第一次递归调用之后),我们将达到

edDistRecursive(['x'], ['y'])

这就是我所说的“递归的最低级别”,但它确实是“倒数第二级”,因为我们关于来达到基本情况。

所以a = ['x']和b = ['y']。我们现在进入功能并检查前两个ifs:
* len(a)== 0?第
* len(b)== 0?第
*计算delta = 1
* return edDistRecursive(a[:-1], b[:-1]) + delta,
  edDistRecursive(a[:-1], b) + 1,
  edDistRecursive(a, b[:-1]) + 1

现在Python将评估第一个递归调用,因为它必须在实际返回之前执行此操作。

第一次递归调用将是edDistRecursive([], [])。我们现在看看会发生什么:
* len(a)== 0?是的,已达到基本情况 - 返回len(b)= 0

所以现在我们回到一个级别,回到之前的返回声明:
return 0 + 1, edDistRecursive(a[:-1], b) + 1, edDistRecursive(a, b[:-1]) + 1

edDistRecursive(a[:-1], b)将评估为edDistRecursive([], ['y']) 我们现在检查一下这个问题:
* len(a)== 0?是的,已达到基本情况 - 返回len(b)= 1

再次回到return语句:
return 0 + 1, 1 + 1, edDistRecursive(a, b[:-1])

edDistRecursive(a, b[:-1])将评估为edDistRecursive(['x'], [])。 这是在这个级别评估的最后一次调用:
* len(a)== 0?第
* len(b)== 0?是 - 返回len(a)= 1

再一次,让我们看看return语句,它现在可以实际返回:
return 1, 2, 1 + 1

好的,所以我们进入的递归调用的结果是元组(1, 2, 2)
当它返回到调用它的edDistRecursive(比如edDistRecursive(['x','k'], ['y','e']))时,那就是异常被引发的时候:

return (1, 2, 2) + delta, edDistRecursive(a[:-1], b) + 1, ...
       |---------------|
       this will raise the exception

我强烈建议您绘制一个与此类似的示例并检查所有递归步骤。尝试不使用min,然后用min尝试 - 你应该注意到在某些级别返回的内容有所不同。

答案 1 :(得分:3)

目前还不清楚“如果我在没有min的情况下运行它”是什么意思,确切地说,但这是显而易见的:表格的陈述

return min(x, y, z)

返回xyz中最小的一个,但是表单的声明

return x, y, z

返回带有三个元素(x, y, z)的元组。

这么简单吗?

思考

英语在这里不起作用;-)看一个更简单的例子,它有完全相同的问题:

def f(n):
    if n < 5:
        return n + 1
    return min(f(n // 2) + 1, f(n // 3) + 7)

然后,例如,

>>> f(100)
9

现在带走min

def f(n):
    if n < 5:
        return n + 1
    return (f(n // 2) + 1, f(n // 3) + 7)

然后:

>>> f(100)
Traceback (most recent call last):
  ...
TypeError: can only concatenate tuple (not "int") to tuple

只能建议您逐行工作,直到指示灯亮起。你原来的问题应该变得清晰明了。

答案 2 :(得分:2)

问题出现在以下部分:

edDistRecursive(a[:-1], b[:-1]) + delta

请记住delta是一个数字。您只能为数字添加数字。但是,如果先前对edDistRecursive(a[:-1], b[:-1])的调用返回一个元组(比如说(1,2,3)),那么,您正在尝试进行计算:

(1,2,3) + delta

哪个错误。