新的尾递归装饰器 [英] New tail recursion decorator

查看:47
本文介绍了新的尾递归装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

http://aspn.activestate.com/ASPN /Coo.../Recipe/496691

解决方案

Kay Schluehr写道:

http://aspn.activestate.com/ ASPN / Coo ... / Recipe / 496691




整洁。


Diez




Diez B. Roggisch写道:

Kay Schluehr写道:

http://aspn.activestate.com/ASPN/Coo ... / Recipe / 496691



整洁。

Diez




Hi Diez,


适用于已复制并粘贴原始解决方案的所有人和b
玩这个我为最新版本的激进变化道歉(

配方现在是版本1.5! )。最新的实现再次比前一个实现更快。
。它不仅可以摆脱

异常,还可以进行堆栈检查。


问候,

Kay


Kay Schluehr写道:


Diez B. Roggisch写道:

Kay Schluehr写道:

> http://aspn.activestate.com/ASPN/Coo。 ../Recipe/496691



整洁。

Diez



Hi Diez,配方现在是1.5版本!)。最新的实现再次比前一个实现快得多。它不仅可以消除例外情况,还可以消除堆栈框架检查。

问候,
Kay



我''我不相信这一点。你必须认识到该函数正在使用

尾递归,然后你必须使用尾递归修改代码以知道它是

。这并不总是微不足道的。例如,给定的

示例是:


@tail_recursion

def factorial(n,acc = 1):

"计算一个阶乘

如果n == 0:

返回acc

res = factorial(n- 1,n * acc)

返回res


但是更常用的写函数方法是:


@tail_recursion

def factorial(n):

"计算一个阶乘

如果n == 0:

返回1

返回n * factorial(n-1)


因为它实际上不是尾递归而不能工作,但它看起来很接近尾递归,它可能会误导很多人,期待它会起作用。如果你不得不以高跷的方式重写

函数,并且他们使用简单的尾递归,那么为什么

不仅仅是因为首先将尾递归分解出来。


我的另一个问题是,装饰者非常脆弱,尽管

这可能是可以解决的。例如(使用已发布的示例)异常

在函数内部使得将来的调用返回垃圾:

factorial(3)
6 factorial(''a'')


Traceback(最近一次调用最后一次):

档案"< pyshell#5>",第1行,在-toplevel-

factorial('''')

文件"< pyshell#1> ;",第12行,结果

tc = g(* args,** kwd)

文件"< pyshell#3>",第6行,在factorial中

res = factorial(n-1,n * acc)

TypeError:不支持的操作数类型 - :''str''和'' int''factial(3)



(''继续'',(3,),{})


http://aspn.activestate.com/ASPN/Coo.../Recipe/496691

解决方案

Kay Schluehr wrote:

http://aspn.activestate.com/ASPN/Coo.../Recipe/496691



Neat.

Diez



Diez B. Roggisch wrote:

Kay Schluehr wrote:

http://aspn.activestate.com/ASPN/Coo.../Recipe/496691



Neat.

Diez



Hi Diez,

for all those who already copied and pasted the original solution and
played with it I apologize for radical changes in the latest version (
the recipe is on version 1.5 now ! ). The latest implementation is
again a lot faster than the previous one. It does not only get rid of
exceptions but also of stack-frame inspection.

Regards,
Kay


Kay Schluehr wrote:


Diez B. Roggisch wrote:

Kay Schluehr wrote:

> http://aspn.activestate.com/ASPN/Coo.../Recipe/496691



Neat.

Diez



Hi Diez,

for all those who already copied and pasted the original solution and
played with it I apologize for radical changes in the latest version (
the recipe is on version 1.5 now ! ). The latest implementation is
again a lot faster than the previous one. It does not only get rid of
exceptions but also of stack-frame inspection.

Regards,
Kay


I''m not convinced by this. You have to recognise that the function is using
tail recursion, and then you have to modify the code to know that it is
using tail recursion. This is not always trivial. For example, the given
example is:

@tail_recursion
def factorial(n, acc=1):
"calculate a factorial"
if n == 0:
return acc
res = factorial(n-1, n*acc)
return res

but a more common way to write the function would be:

@tail_recursion
def factorial(n):
"calculate a factorial"
if n == 0:
return 1
return n * factorial(n-1)

which won''t work because it isn''t actually tail recursion, but it looks
sufficiently close to tail recursion that it would probably mislead a lot
of people into expecting it will work. If you are going to have to rewrite
functions in a stilted manner, and they use simple tail recursion, then why
not just factor out the tail recursion in the first place.

My other problem with this is that the decorator is very fragile although
this may be fixable. e.g. (using the published example) an exception
thrown inside the function makes future calls return garbage:

factorial(3) 6 factorial(''a'')
Traceback (most recent call last):
File "<pyshell#5>", line 1, in -toplevel-
factorial(''a'')
File "<pyshell#1>", line 12, in result
tc = g(*args,**kwd)
File "<pyshell#3>", line 6, in factorial
res = factorial(n-1, n*acc)
TypeError: unsupported operand type(s) for -: ''str'' and ''int'' factorial(3)


(''continue'', (3,), {})


这篇关于新的尾递归装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆