builtins.TypeError: catching classes that do not inherit from BaseException is not allowed
hongy...@gmail.com
hongyi.zhao at gmail.com
Thu Dec 30 08:04:24 EST 2021
I try to compute the factorial of a large number with tail-recursion optimization decorator in Python3. The following code snippet is converted from the code snippet given here [1] by the following steps:
$ pyenv shell datasci
$ python --version
Python 3.9.1
$ pip install 2to3
$ 2to3 -w this-script.py
```
# This program shows off a python decorator(
# which implements tail call optimization. It
# does this by throwing an exception if it is
# its own grandparent, and catching such
# exceptions to recall the stack.
import sys
class TailRecurseException:
def __init__(self, args, kwargs):
self.args = args
self.kwargs = kwargs
def tail_call_optimized(g):
"""
This function decorates a function with tail call
optimization. It does this by throwing an exception
if it is its own grandparent, and catching such
exceptions to fake the tail call optimization.
This function fails if the decorated
function recurses in a non-tail context.
"""
def func(*args, **kwargs):
f = sys._getframe()
if f.f_back and f.f_back.f_back \
and f.f_back.f_back.f_code == f.f_code:
raise TailRecurseException(args, kwargs)
else:
while 1:
try:
return g(*args, **kwargs)
except TailRecurseException as e:
args = e.args
kwargs = e.kwargs
func.__doc__ = g.__doc__
return func
@tail_call_optimized
def factorial(n, acc=1):
"calculate a factorial"
if n == 0:
return acc
return factorial(n-1, n*acc)
print(factorial(10000))
# prints a big, big number,
# but doesn't hit the recursion limit.
@tail_call_optimized
def fib(i, current = 0, next = 1):
if i == 0:
return current
else:
return fib(i - 1, next, current + next)
print(fib(10000))
# also prints a big number,
# but doesn't hit the recursion limit.
```
However, when I try to test the above script, the following error will be triggered:
```
$ python this-script.py
Traceback (most recent call last):
File "/home/werner/this-script.py", line 32, in func
return g(*args, **kwargs)
File "/home/werner/this-script.py", line 44, in factorial
return factorial(n-1, n*acc)
File "/home/werner/this-script.py", line 28, in func
raise TailRecurseException(args, kwargs)
TypeError: exceptions must derive from BaseException
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/werner/this-script.py", line 46, in <module>
print(factorial(10000))
File "/home/werner/this-script.py", line 33, in func
except TailRecurseException as e:
TypeError: catching classes that do not inherit from BaseException is not allowed
```
Any hints for fixing this problem will be highly appreciated.
[1] https://stackoverflow.com/q/27417874
Regards,
HZ
More information about the Python-list
mailing list