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
所需的编辑次数。我想如果我毫不费力地运行它,我将能够看到每个函数产生了多少次编辑。
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
,但我遇到了同样的错误。
有没有办法获得每个函数的值,这是我最初的目标?
答案 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)
返回x
,y
和z
中最小的一个,但是表单的声明
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
哪个错误。