Skip to main content
 首页 » 编程设计

python之为什么这个函数与 min 一起工作,而不是没有

2025年05月04日12落叶无声

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 

这是遗传学中使用的一种算法(近似匹配),用于确定匹配a 和b 需要编辑多少次。我想如果我在没有 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 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 值并没有被添加到整个元组中。事实上,元组由(函数+整数)组成。所以当元组本身的元素是(函数+ 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,但我遇到了同样的错误。

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

请您参考如下方法:

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

编辑:让我们一步步看一个例子,以便我们可以更直接地查看正在发生的事情。对于此示例,让我们不使用 min 以便我们可以看到问题出在哪里。

为使示例简单,假设我们从

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

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

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

这就是我所说的“递归的最低级别”,但它实际上是“倒数第二个级别”,因为我们即将达到基本情况。

因此 a = ['x'] 和 b = ['y']。我们现在进入函数并检查前两个 if:
* len(a) == 0 吗?没有。
* len(b) == 0 吗?没有。
* 计算 delta = 1
* 返回 edDistRecursive(a[:-1], b[:-1]) + delta,
edDistRecursive(a[:-1], b) + 1,
edDistRecursive(a, b[:-1]) + 1

现在 Python 将评估第一个递归调用,因为它必须这样做才能真正返回一些东西。

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

现在我们回到上一层,回到之前的返回语句:
返回 0 + 1, edDistRecursive(a[:-1], b) + 1, edDistRecursive(a, b[:-1]) + 1

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

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

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

再一次,让我们看一下返回语句,现在可以实际返回了:
返回 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 尝试 - 您应该注意到在某些级别返回的内容有所不同。