No, and it never will since Guido van Rossum prefers to be able to have proper tracebacks:

Tail Recursion Elimination (2009-04-22)

Final Words on Tail Calls (2009-04-27)

You can manually eliminate the recursion with a transformation like this:

>>> def trisum(n, csum):
...     while True:                     # Change recursion to a while loop
...         if n == 0:
...             return csum
...         n, csum = n - 1, csum + n   # Update parameters instead of tail recursion

>>> trisum(1000,0)
500500
Answer from John La Rooy on Stack Overflow
🌐
Chrispenner
chrispenner.ca › posts › python-tail-recursion
Tail Recursion In Python
Our decorator gets around that problem by continually entering and exiting a single call, so technically our function isn't actually recursive anymore and we avoid the limits. I tested out both versions, the normal version hits the tail-recursion limit at factorial(980) whereas the tail-recursive version will happily compute numbers as large as your computer can handle.
🌐
GeeksforGeeks
geeksforgeeks.org › dsa › tail-recursion-in-python
Tail Recursion in Python - GeeksforGeeks
July 23, 2025 - In this function, the recursive call to factorial_tail_recursive is the last operation, making it tail-recursive. Since Python does not optimize tail recursion, we can convert the tail-recursive function to an iterative version to avoid potential stack overflow issues.
Discussions

Does Python optimize tail recursion? - Stack Overflow
I have the following piece of code which fails with the following error: RuntimeError: maximum recursion depth exceeded I attempted to rewrite this to allow for tail call optimization (TCO). I be... More on stackoverflow.com
🌐 stackoverflow.com
Tail recursion in Python
lru_cache, from the functools library · The example given in the docs [0] is: More on news.ycombinator.com
🌐 news.ycombinator.com
80
193
March 18, 2018
Does python support Tail-Recursion
Python doesn't optimise tail-calls, so no. At least not right now. That said you're generally better-off with iterative solutions anyway unless the problem in question is either too complex to be effectively solved iteratively, or the recursion depth limit cannot reasonably ever be reached (eg. when traversing the filesystem, you're not going to run into a situation in practice where there would be directory trees much deeper than 30 nodes). For instance, there exists a really great iterative solution for the Fibonacci sequence: def fib(): a, b = 0, 1 while True: yield a a, b = b, a+b More on reddit.com
🌐 r/learnpython
7
2
October 6, 2021
algorithm - What is tail recursion? - Stack Overflow
This point is important because ... known as Tail Call Optimization(TCO). NB. Do bear in mind that the example above is written in Python whose runtime does not support TCO. This is just an example to explain the point. TCO is supported in languages like Scheme, Haskell etc ... Here is a quick code snippet comparing two functions. The first is traditional recursion for finding ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Kylem
kylem.net › programming › tailcall.html
Tail call recursion in Python - Kyle Miller
Programming languages like Scheme depend on tail calls being eliminated for control flow, and it’s also necessary for continuation passing style.[2] Our running example is going to be the factorial function (a classic), written with an accumulator argument so that its recursive call is a tail call: def fact(n, r=1) : if n <= 1 : return r else : return fact(n-1, n*r) If n is too large, then this recursive function will overflow the stack, despite the fact that Python can deal with really big integers.
🌐
Medium
helenrensiyu.medium.com › tail-recursion-in-python-2d8d839d5146
Tail Recursion in Python. The concept of recursion, which in the… | by Helen Ren | Medium
March 17, 2022 - For example, we will encounter maximum recursion depth exceeded in comparison in Python when trying to find the factorial of 10000 using the function we just created. Is there a way to optimise it if we still want to use recursion? Yes, there is this concept called Tail Recursion Optimisation.
Top answer
1 of 8
324

No, and it never will since Guido van Rossum prefers to be able to have proper tracebacks:

Tail Recursion Elimination (2009-04-22)

Final Words on Tail Calls (2009-04-27)

You can manually eliminate the recursion with a transformation like this:

>>> def trisum(n, csum):
...     while True:                     # Change recursion to a while loop
...         if n == 0:
...             return csum
...         n, csum = n - 1, csum + n   # Update parameters instead of tail recursion

>>> trisum(1000,0)
500500
2 of 8
232

I published a module performing tail-call optimization (handling both tail-recursion and continuation-passing style): https://github.com/baruchel/tco

Optimizing tail-recursion in Python

It has often been claimed that tail-recursion doesn't suit the Pythonic way of coding and that one shouldn't care about how to embed it in a loop. I don't want to argue with this point of view; sometimes however I like trying or implementing new ideas as tail-recursive functions rather than with loops for various reasons (focusing on the idea rather than on the process, having twenty short functions on my screen in the same time rather than only three "Pythonic" functions, working in an interactive session rather than editing my code, etc.).

Optimizing tail-recursion in Python is in fact quite easy. While it is said to be impossible or very tricky, I think it can be achieved with elegant, short and general solutions; I even think that most of these solutions don't use Python features otherwise than they should. Clean lambda expressions working along with very standard loops lead to quick, efficient and fully usable tools for implementing tail-recursion optimization.

As a personal convenience, I wrote a small module implementing such an optimization by two different ways. I would like to discuss here about my two main functions.

The clean way: modifying the Y combinator

The Y combinator is well known; it allows to use lambda functions in a recursive manner, but it doesn't allow by itself to embed recursive calls in a loop. Lambda calculus alone can't do such a thing. A slight change in the Y combinator however can protect the recursive call to be actually evaluated. Evaluation can thus be delayed.

Here is the famous expression for the Y combinator:

lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))

With a very slight change, I could get:

lambda f: (lambda x: x(x))(lambda y: f(lambda *args: lambda: y(y)(*args)))

Instead of calling itself, the function f now returns a function performing the very same call, but since it returns it, the evaluation can be done later from outside.

My code is:

def bet(func):
    b = (lambda f: (lambda x: x(x))(lambda y:
          f(lambda *args: lambda: y(y)(*args))))(func)
    def wrapper(*args):
        out = b(*args)
        while callable(out):
            out = out()
        return out
    return wrapper

The function can be used in the following way; here are two examples with tail-recursive versions of factorial and Fibonacci:

>>> from recursion import *
>>> fac = bet( lambda f: lambda n, a: a if not n else f(n-1,a*n) )
>>> fac(5,1)
120
>>> fibo = bet( lambda f: lambda n,p,q: p if not n else f(n-1,q,p+q) )
>>> fibo(10,0,1)
55

Obviously recursion depth isn't an issue any longer:

>>> bet( lambda f: lambda n: 42 if not n else f(n-1) )(50000)
42

This is of course the single real purpose of the function.

Only one thing can't be done with this optimization: it can't be used with a tail-recursive function evaluating to another function (this comes from the fact that callable returned objects are all handled as further recursive calls with no distinction). Since I usually don't need such a feature, I am very happy with the code above. However, in order to provide a more general module, I thought a little more in order to find some workaround for this issue (see next section).

Concerning the speed of this process (which isn't the real issue however), it happens to be quite good; tail-recursive functions are even evaluated much quicker than with the following code using simpler expressions:

def bet1(func):
    def wrapper(*args):
        out = func(lambda *x: lambda: x)(*args)
        while callable(out):
            out = func(lambda *x: lambda: x)(*out())
        return out
    return wrapper

I think that evaluating one expression, even complicated, is much quicker than evaluating several simple expressions, which is the case in this second version. I didn't keep this new function in my module, and I see no circumstances where it could be used rather than the "official" one.

Continuation passing style with exceptions

Here is a more general function; it is able to handle all tail-recursive functions, including those returning other functions. Recursive calls are recognized from other return values by the use of exceptions. This solutions is slower than the previous one; a quicker code could probably be written by using some special values as "flags" being detected in the main loop, but I don't like the idea of using special values or internal keywords. There is some funny interpretation of using exceptions: if Python doesn't like tail-recursive calls, an exception should be raised when a tail-recursive call does occur, and the Pythonic way will be to catch the exception in order to find some clean solution, which is actually what happens here...

class _RecursiveCall(Exception):
  def __init__(self, *args):
    self.args = args
def _recursiveCallback(*args):
  raise _RecursiveCall(*args)
def bet0(func):
    def wrapper(*args):
        while True:
          try:
            return func(_recursiveCallback)(*args)
          except _RecursiveCall as e:
            args = e.args
    return wrapper

Now all functions can be used. In the following example, f(n) is evaluated to the identity function for any positive value of n:

>>> f = bet0( lambda f: lambda n: (lambda x: x) if not n else f(n-1) )
>>> f(5)(42)
42

Of course, it could be argued that exceptions are not intended to be used for intentionally redirecting the interpreter (as a kind of goto statement or probably rather a kind of continuation passing style), which I have to admit. But, again, I find funny the idea of using try with a single line being a return statement: we try to return something (normal behaviour) but we can't do it because of a recursive call occurring (exception).

Initial answer (2013-08-29).

I wrote a very small plugin for handling tail recursion. You may find it with my explanations there: https://groups.google.com/forum/?hl=fr#!topic/comp.lang.python/dIsnJ2BoBKs

It can embed a lambda function written with a tail recursion style in another function which will evaluate it as a loop.

The most interesting feature in this small function, in my humble opinion, is that the function doesn't rely on some dirty programming hack but on mere lambda calculus: the behaviour of the function is changed to another one when inserted in another lambda function which looks very like the Y combinator.

🌐
Invent with Python
inventwithpython.com › recursion › chapter8.html
Chapter 8 - Tail Call Optimization
Tail recursive functions require rearranging their code to make them suitable for the tail call optimization feature of the compiler or interpreter. However, not all compilers and interpreters offer tail call optimization as a feature. Notably, CPython (the Python interpreter downloaded from https://python.org) does not implement tail call optimization.
🌐
Medium
medium.com › @tssovi › tail-recursion-and-head-recursion-d9aeb8478b12
Tail Recursion and Head Recursion | by Tusamma Sal Sabil | Medium
March 24, 2020 - Tail recursion is just a particular instance of recursion, where the return value of a function is calculated as a call to itself, and nothing else. # normal recursive of factorial def factorial(n): if n == 0: return 1 else: return n * factorial(n ...
Find elsewhere
🌐
C# Corner
c-sharpcorner.com › article › what-is-tail-recursion-and-how-to-use-it-in-functional-programming
What is Tail Recursion and its Benefits in Functional Programming
October 6, 2025 - Tail recursion reuses the same memory space instead of creating new stack frames every time. This makes your recursive function faster, safer, and memory-efficient. Although Python doesn’t perform tail call optimization (TCO) by default like ...
🌐
Hacker News
news.ycombinator.com › item
Tail recursion in Python | Hacker News
March 18, 2018 - lru_cache, from the functools library · The example given in the docs [0] is:
🌐
Sagnibak
sagnibak.github.io › blog › python-is-haskell-tail-recursion
Python is the Haskell You Never Knew You Had: Tail Call Optimization
August 16, 2020 - The decorator should be a higher-order function which takes in a function fn and returns an inner function which when called, calls fn, but with some scaffolding. fn must follow a specific form: it must return something which instructs the inner function (often called the trampoline function) whether it wants to recurse or return. For this, we need two classes representing the two cases: fn should return an instance of TailCall when it wants to make a tail recursive call, and it should feed the arguments of the next call into the instance.
🌐
Medium
medium.com › @chamod.14_80003 › tail-recursion-81f086b5b174
Tail Recursion. Tail recursion is an efficient way of… | by Chamod Samarajeewa | Medium
July 2, 2017 - Here is how the tail recursive method call happens. ... Here, the tree does not grow with the depth. The reason is that at every recursive call, the previous stack frame is replaced by the new one instead of pushing another stack frame. Therefore, stack over flow error does not occur. Follow the below code in Python to get an understanding about the performance difference of normal recursive calls and tail recursive calls.
Top answer
1 of 16
2128

Consider a simple function that adds the first N natural numbers. (e.g. sum(5) = 0 + 1 + 2 + 3 + 4 + 5 = 15).

Here is a simple JavaScript implementation that uses recursion:

function recsum(x) {
    if (x === 0) {
        return 0;
    } else {
        return x + recsum(x - 1);
    }
}

If you called recsum(5), this is what the JavaScript interpreter would evaluate:

recsum(5)
5 + recsum(4)
5 + (4 + recsum(3))
5 + (4 + (3 + recsum(2)))
5 + (4 + (3 + (2 + recsum(1))))
5 + (4 + (3 + (2 + (1 + recsum(0)))))
5 + (4 + (3 + (2 + (1 + 0))))
5 + (4 + (3 + (2 + 1)))
5 + (4 + (3 + 3))
5 + (4 + 6)
5 + 10
15

Note how every recursive call has to complete before the JavaScript interpreter begins to actually do the work of calculating the sum.

Here's a tail-recursive version of the same function:

function tailrecsum(x, running_total = 0) {
    if (x === 0) {
        return running_total;
    } else {
        return tailrecsum(x - 1, running_total + x);
    }
}

Here's the sequence of events that would occur if you called tailrecsum(5), (which would effectively be tailrecsum(5, 0), because of the default second argument).

tailrecsum(5, 0)
tailrecsum(4, 5)
tailrecsum(3, 9)
tailrecsum(2, 12)
tailrecsum(1, 14)
tailrecsum(0, 15)
15

In the tail-recursive case, with each evaluation of the recursive call, the running_total is updated.

Note: The original answer used examples from Python. These have been changed to JavaScript, since Python interpreters don't support tail call optimization. However, while tail call optimization is part of the ECMAScript 2015 spec, most JavaScript interpreters don't support it).

2 of 16
844

In traditional recursion, the typical model is that you perform your recursive calls first, and then you take the return value of the recursive call and calculate the result. In this manner, you don't get the result of your calculation until you have returned from every recursive call.

In tail recursion, you perform your calculations first, and then you execute the recursive call, passing the results of your current step to the next recursive step. This results in the last statement being in the form of (return (recursive-function params)). Basically, the return value of any given recursive step is the same as the return value of the next recursive call.

The consequence of this is that once you are ready to perform your next recursive step, you don't need the current stack frame any more. This allows for some optimization. In fact, with an appropriately written compiler, you should never have a stack overflow snicker with a tail recursive call. Simply reuse the current stack frame for the next recursive step. I'm pretty sure Lisp does this.

🌐
Heathhenley
heathhenley.dev › posts › notes-tail-recursion
Simple tail recursion examples - Blogging by Heath™
November 17, 2024 - The first is a simple function to get the length of list recursively: (* Non tail-recursive list len function *) let rec len lst = match lst with | [] -> 0 | _::t -> 1 + len t
🌐
Pritesh-shrivastava
pritesh-shrivastava.github.io › blog › 2020 › 09 › 25 › tree-vs-tail-with-memo
Tree vs Tail Recursion & Memoization - Pritesh Shrivastava’s Blog
September 24, 2020 - Here’s the iterative (tail-recursive) solution from SICP: (define (fib_iter n) (define (helper a b count) (if (= count 0) b (helper (+ a b) a (- count 1)))) (helper 1 0 n)) Notice, how we again define an internal helper function and state variables like we did for the iterative factorial procedure above. Next, I’ll convert the code into Python & see if we can improve the performance.
🌐
GitConnected
levelup.gitconnected.com › functional-programming-and-tail-recursion-in-python-01e0fbc97613
Functional Programming and Tail Recursion in Python | by Manmohan Krishna | Level Up Coding
May 28, 2024 - Python’s Higher Order Functions(HOFs) Tail Recursion and Continuation Passing Style(CPS) Tail recursion is a form of recursion where the recursive call is the last operation in the function. This allows for optimization...
🌐
Hyperskill
hyperskill.org › learn › step › 31784
Tail recursion
Hyperskill is an educational platform for learning programming and software development through project-based courses, that helps you secure a job in tech. Master Python, Java, Kotlin, and more with real-world coding challenges.
🌐
Medium
medium.com › @giorgio.zoppi › tail-recursion-optimization-from-stack-frames-to-python-3-14-a76ba24fb3d1
Tail Recursion Optimization: From Stack Frames to Python 3.14 | by Giorgio Zoppi | Medium
September 27, 2025 - Understanding stack frames and tail calls is key to efficient recursion · Scala provides native support with @tailrec. Python 3.14 introduces tail-call-based opcode dispatch, improving recursion performance.
🌐
Elc
elc.github.io › posts › recursion-python
Python Recursion: a Trampoline from the Mutual Head to the Memoized Nested Tail | Ezequiel Leonardo Castaño Personal Website
May 21, 2023 - It is possible with minimal modifications to the original functions to surpass this limitation and make the language treat the recursive function as an iteration and thus bypass the overflow. This technique is called trampoline and requires the function to be implemented in tail-recursive form. Moreover, the function should defer the evaluation of the tail call by using an anonymous function (in Python called lambdas).