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 尝试 - 您应该注意到在某些级别返回的内容有所不同。
