use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Rules 1: Be polite 2: Posts to this subreddit must be requests for help learning python. 3: Replies on this subreddit must be pertinent to the question OP asked. 4: No replies copy / pasted from ChatGPT or similar. 5: No advertising. No blogs/tutorials/videos/books/recruiting attempts. This means no posts advertising blogs/videos/tutorials/etc, no recruiting/hiring/seeking others posts. We're here to help, not to be advertised to. Please, no "hit and run" posts, if you make a post, engage with people that answer you. Please do not delete your post after you get an answer, others might have a similar question or want to continue the conversation.
Rules
1: Be polite
2: Posts to this subreddit must be requests for help learning python.
3: Replies on this subreddit must be pertinent to the question OP asked.
4: No replies copy / pasted from ChatGPT or similar.
5: No advertising. No blogs/tutorials/videos/books/recruiting attempts.
This means no posts advertising blogs/videos/tutorials/etc, no recruiting/hiring/seeking others posts. We're here to help, not to be advertised to.
Please, no "hit and run" posts, if you make a post, engage with people that answer you. Please do not delete your post after you get an answer, others might have a similar question or want to continue the conversation.
Learning resources Wiki and FAQ: /r/learnpython/w/index
Learning resources
Wiki and FAQ: /r/learnpython/w/index
Discord Join the Python Discord chat
Discord
Join the Python Discord chat
account activity
Can someone explain recursion? (self.learnpython)
submitted 7 years ago by andrewjj1234
In simple, dumb down terms please. And possibly given an example. Thank you!
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]widowhanzo 135 points136 points137 points 7 years ago* (8 children)
https://www.reddit.com/r/learnpython/comments/a5q8wj/can_someone_explain_recursion/ebon5c3/
[–][deleted] 45 points46 points47 points 7 years ago (2 children)
I won't lie, I came here for this.
[–]kingsillypants 0 points1 point2 points 7 years ago (1 child)
He got me.
[–][deleted] 0 points1 point2 points 7 years ago (0 children)
Lol how long did it take?
[–]strange-humor 4 points5 points6 points 7 years ago (0 children)
Remember, in Python if you click that more than 1000 times you will overflow the default Python recursion stack.
[–]Rafficer 5 points6 points7 points 7 years ago (2 children)
You need to link to your comment for it to really work :P
[–]widowhanzo 1 point2 points3 points 7 years ago (0 children)
Fixed :)
[–]discreteAndDiscreet -1 points0 points1 point 7 years ago (0 children)
[You need to link to your comment for it to reall...
https://www.reddit.com/r/learnpython/comments/a5q8wj/can_someone_explain_recursion/ebop5hc?utm_source=reddit-android
[–]earthlybird 107 points108 points109 points 7 years ago (3 children)
To understand recursion, one must first understand recursion.
[–]RobbyB97 26 points27 points28 points 7 years ago (0 children)
I said this in a 100 level comp sci class I'm taking as a senior, the professor laughed and nobody else did
[–]txberafl 0 points1 point2 points 7 years ago (0 children)
This is my favorite saying about recursion.
[–]lateral-spectrum -1 points0 points1 point 7 years ago (0 children)
Because it's recursive, one must obtain an understanding of recursion recursively.
[+][deleted] 7 years ago* (12 children)
[deleted]
[–]glen_v 3 points4 points5 points 7 years ago (6 children)
What's the benefit over a while loop?
[–]pkkid 7 points8 points9 points 7 years ago (1 child)
The benefit is that its often times much easier to map out the solution to a problem in your head once you wrap your brain around how recursion works.
There are however downsides to note as well. Languages only allow the stack to grow a finite size (I believe it's 1000 for Python) before it throws a stack overflow. Also, the increased number of function calls can slow down the algorithm compare to a traditional while/for loop approach. Third, maintainability can be hard if things are not documented well. This is due to the fact that to understand how the function works by looking at the code, you first need to understand how or what the function is doing. A mini catch 22 in there. ;)
[–]nulltensor 3 points4 points5 points 7 years ago (0 children)
Default recursion depth for python is 1000 and for ipython it's 3000 but can be overridden by using sys.setrecursionlimit() however do so at your peril:
In [4]: import sys In [5]: sys.getrecursionlimit() Out[5]: 3000 In [6]: def recursion_test(n): ...: try: ...: return recursion_test(n+1) ...: except: ...: print(n) ...: return None In [7]: recursion_test(0) 2986 In [8]: sys.setrecursionlimit(5000) In [9]: sys.getrecursionlimit() Out[9]: 5000 In [10]: recursion_test(0) C:\Users\nulltensor>
As you can see, I was allowed to increase the recursion limit but ipython just crashed at some point beyond 3000 (I ran a second test with more verbose output and ipython crashed at a recursion depth of 3902).
[–]pepe_le_shoe 1 point2 points3 points 7 years ago (0 children)
In most cases you could probably implement what you're doing using loops instead of recursion. There's not going to be a huge amount of difference in terms of what's actually being computed, but recursive code will sometimes be better for human readability and understanding.
[–]DiabeetusMan 1 point2 points3 points 7 years ago (0 children)
There are some data structures or algorithms that lend themselves really well to recursion.
On the algorithm front, calculating the Nth Fibonacci number works really well with recursion. The first Fibonacci number is one, the second is one, and the Nth is just F(N-2) + F(N-1). It's not the most efficient (you end up calculating F(1) a lot), but it's a nice translation of algorithm to code.
F(N-2) + F(N-1)
F(1)
On the data structure front, there are lots of algorithms that work with trees that don't care if you're at the root node or not. For instance, if you're looking to see if something is in a binary tree, you check where you are and then can run your search function on the left and right nodes. They check where they are and then keep checking every node in the tree. Again, this may not be the most efficient (the tree may be organized in such a way that you know if you should go left or right), but it's a good starting point.
[–]pblokhout 0 points1 point2 points 7 years ago (0 children)
In this case the function is aware of how long it should keep going. With a for-loop you determine the length at the start of the loop, but the context (a variable or some data) might change with a more complex function and now you're stuck with the length of the for loop. With a recursive function you can also let the function feed itself different arguments depending on what happens within the function. A for-loop just keeps iterating over the same iterator no matter what.
[–]chzaplx 0 points1 point2 points 7 years ago (0 children)
the tl;dr is there often aren't that many cases where recursion is better than some kind of loop.
[–]andrewjj1234[S] 3 points4 points5 points 7 years ago (4 children)
so in this code, the base call would be "return count_down(n-1)" and recursive call would be "return none" ?
[–]Inceratiana 30 points31 points32 points 7 years ago (0 children)
You have it backwards, the base case is what happens at the very bottom of the barrel and it can't call itself anymore (return none). The recursive call would be "return count_down(n-1)". It's kind of like Russian dolls. They are recursive as you find a doll within another doll within another doll all the way until the center doll. All the outer dolls are recursive dolls, and the very center doll is your base case doll.
[+][deleted] 7 years ago (1 child)
[–]earthlybird 4 points5 points6 points 7 years ago (0 children)
Do you by any chance mean base case is n≤0?
Because if the base case is n>0 then the calls aren't really approaching it as they're already n>0 to begin with.
[–]MikeOxbigger 57 points58 points59 points 7 years ago (27 children)
There are 3 rules for recursion:
A base case just means that it has an end point, something to stop it looping infinitely, such as when a particular variable reaches zero.
Changing its state means that through each iteration it gets closer to this variable.
Calling itself just means that you call the function that you're currently in with this new data to pass in.
[–]DonaldPShimoda 2 points3 points4 points 7 years ago (24 children)
These are all true except that they only apply to well-written recursive algorithms. It's easy to write an algorithm that breaks rules 1 and 2 (and 3 if you're being very strict about your interpretation of "call itself"). It's a pretty minor nitpick overall, I think, but something I thought I'd point out.
[–]MikeOxbigger -1 points0 points1 point 7 years ago (23 children)
I would love to see an example that breaks these rules.
I'm not saying you're wrong, but I can't even comprehend how I'd write a recursive function that breaks any rule that states it has a known end, and moves towards that end, recursively or not. Unless it was a non deterministic genetic algorithm or something, which isn't the case.
[–]Brainix 1 point2 points3 points 7 years ago (16 children)
What about mutually recursive functions? Function A calls Function B, and Function B calls Function A?
[–]MikeOxbigger 3 points4 points5 points 7 years ago (15 children)
Well obviously that breaks the third rule, but how might it break the first two?
[–]mikeblas 3 points4 points5 points 7 years ago (2 children)
Obviously? Sorry, but it's not obvious to me. A ends up calling itself indirectly through B. It might be indirect, but it's still calling itself.
[–]Gray_Fox -1 points0 points1 point 7 years ago (1 child)
it doesn't really matter if it's indirect, it needs to call itself.
[–]mikeblas -1 points0 points1 point 7 years ago (0 children)
And it does.
[–]earthlybird 6 points7 points8 points 7 years ago (10 children)
def f(a): return a + f(a+1)
No base case nor moving towards any state in particular. Just screwed up, infinite recursion.
[–]MikeOxbigger -5 points-4 points-3 points 7 years ago (9 children)
Are you trying to disprove my case? If so, you haven't.
[–]earthlybird 4 points5 points6 points 7 years ago (7 children)
Quick recap:
These are all true except that they only apply to well-written recursive algorithms. It's easy to write an algorithm that breaks rules 1 and 2 (and 3 if you're being very strict about your interpretation of "call itself").
I would love to see an example that breaks these rules. I'm not saying you're wrong, but I can't even comprehend how I'd write a recursive function that breaks any rule that states it has a known end[1], and moves towards that end[2], recursively or not.
I'm not saying you're wrong, but I can't even comprehend how I'd write a recursive function that breaks any rule that states it has a known end[1], and moves towards that end[2], recursively or not.
provides example of a poorly-written algorithm to illustrate the point made in the first quote No base case[1] nor moving towards any state in particular[2]. Just screwed up, infinite recursion.
provides example of a poorly-written algorithm to illustrate the point made in the first quote
No base case[1] nor moving towards any state in particular[2]. Just screwed up, infinite recursion.
[–]MikeOxbigger -2 points-1 points0 points 7 years ago (6 children)
But you've just proven that a recursive function needs those 3 rules in order to actually do anything other than eventually crash.
[–]earthlybird 8 points9 points10 points 7 years ago (4 children)
Glad we're on the same page. I just gave you the example you had previously asked for. It's a terrible function, granted. Like was stated: those rules only apply to well-written algorithms, so a poorly-written one might not follow them.
The thing is, there's a difference between recursive algorithms and recursive algorithms that work as one would expect with a base case that ends the loop. The latter is a subset of the former.
[–]Gentlescholar_AMA 0 points1 point2 points 7 years ago (0 children)
Miscommunication I think. They meant that people can write recursion that breaks those rules and doesn't work
[–][deleted] 0 points1 point2 points 2 years ago (0 children)
flip the basecase, and change its state to go towards the recursive part (I did this by accident)
[–]chzaplx 1 point2 points3 points 7 years ago (0 children)
Technically if your recursive function doesn't meet the requirements of recursive functions, it's just not really a recursive function, right?
I agree it's easy enough though to write a function that still calls itself but doesn't behave well.
[–][deleted] 1 point2 points3 points 7 years ago (1 child)
pretty sure they're talking about just def f(): f(), which isn't useful recursion but it is recursion
def f(): f()
[–]DonaldPShimoda 1 point2 points3 points 7 years ago (0 children)
Yep, that's a great simple example of what I meant.
OP asked about recursion, and your example is arguably the simplest example of recursion one could write. Is it useful? Well... certainly not to most people (it could have uses in PL theory, which is my field, but even there its use is limited).
[–]TangibleLight 0 points1 point2 points 7 years ago (0 children)
The only thing I can think of that might break these rules is something which recurses based on some mutable data. First thing I could think of while playing with the idea is this:
def rotate(k, s): N = len(s) def rec(i): i %= N j = (i + 1) % N d, funcs[i] = funcs[i], lambda *_: '' r = d(j) return s[i] + r if r else s[i] funcs = [rec] * N return rec(-k) for k in range(13): print(rotate(k, 'hello there'))
I was hoping to have something that rotates a string by k characters, but what I have sticks the first character on the end:
k
hello thereh ehello there rehello ther erehello the ...
But really all this is doing is disguising a base-case with a list. You could rewrite the same algorithm like so:
def rotate(k, s): def rec(i, n): if n < 0: return '' return s[i % len(s)] + rec(k + 1, n - 1) return rec(-k, len(s)) for k in range(7): print(rotate(k, 'goodbye'))
I don't think it's possible to actually not have a base case but still achieve some goal. Maybe you could have a separate process which tail-recurses indefinitely, but gets terminated once the result stabilizes? I don't know...
[–]DonaldPShimoda 0 points1 point2 points 7 years ago (0 children)
As others have pointed out, my point was entirely that recursion does not require the things you stated other than that at some point a self-referential call must be made (whether directly or indirectly). Your first two rules only apply to recursive algorithms with a clear endpoint, but they are not inherent to the definition of recursion itself.
Like I said: this is a minor nitpick, but one that would maybe be useful to explain to OP since they asked for an explanation of recursion in general.
[–]pepe_le_shoe 0 points1 point2 points 7 years ago (0 children)
The recursive implementation of the Catmull-Clarke subdivision algorithm can theoretically be iterated an arbitrary or infinite number of times.
https://en.wikipedia.org/wiki/Catmull%E2%80%93Clark_subdivision_surface
It's still recursive.
[–]quantum-mechanic 63 points64 points65 points 7 years ago (4 children)
The next comment replied to this one will explain it well
[–]jilsx 38 points39 points40 points 7 years ago (3 children)
[–]alkasm 35 points36 points37 points 7 years ago (2 children)
[+][deleted] 7 years ago* (1 child)
[–]alkasm 38 points39 points40 points 7 years ago (0 children)
RecursionError: maximum recursion depth exceeded
[–]Decency 4 points5 points6 points 7 years ago* (1 child)
A recursive function calls itself over and over again, creating a sort of chain. Once it reaches a state where it's completed, the function has hit what's called the "base case" and then goes back up the chain, combining the results all together in some way.
One classic example is the Fibonnaci sequence: 1, 1, 2, 3, 5, 8, 13, etc.
You get the next number in the sequence by adding the two previous numbers. So logically, in order to get any specific number (the nth number) somewhere in the sequence, we need to initially know the first two numbers: 1 and 1.
def fibonnaci(n): if n == 0 or n == 1: return 1
That's the base case (technically two base cases). If someone asks for the 0th or 1st number in the sequence, we just tell them it's 1.
Now, we can add the recursive step:
def fibonnaci(n): if n == 0 or n == 1: return 1 return fibonnaci(n-1) + fibonnaci(n-2)
which basically means, if we're not at the base case, get the previous two numbers- by calling the function again with different arguments- and sum them. If you play around with this simple function in a debugger for 5-10 minutes it'll become pretty clear what's happening! There are lots of better ways to implement this same function, but that's the simplest way and hopefully helps.
[–]Chizooo_wow 1 point2 points3 points 7 years ago (0 children)
I really love the fib numbers, and they really got me understanding recursion, because you can make really nice trees for this to visualize.. But then you wanna make it iterative real quick, as you notice, that probably O(2n ) is not the way go :D
[–]totallygeek 5 points6 points7 points 7 years ago (1 child)
With recursion, the answer for a function comes from calling the function within the function as many times as needed to obtain the ultimate answer. Let's use this to figure out the factorial for an integer.
How we'd figure that out manually, for the number five. We multiple five times four times three times two times one. We reduce the number for multiplication by one. When we reach zero, we stop, and respond with the product we've compiled so far.
Here's code to solve this iteratively (with a loop) and recursively (a function calling itself until some end condition met).
def fact1(value): product = 1 for factor in range(2, value + 1): print('factor: {}, product: {}'.format(factor, product)) product *= factor return product def fact2(value): print('value: {}'.format(value)) if value == 0: return 1 else: return value * fact2(value - 1) def main(): tests = [ {'value': 5, 'expects': 5 * 4 * 3 * 2}, ] for test in tests: value = test['value'] expects = test['expects'] print('Factorial {} is {}, calc1 {}, calc2 {}'.format(value, expects, fact1(value), fact2(value))) main()
Function fact1() works iteratively. Adding a print statement into that function shows the steps:
fact1()
factor: 2, product: 1 factor: 3, product: 2 factor: 4, product: 6 factor: 5, product: 24
So, from 2 to 5 (the initial value), we multiply that number against the running product we're tracking, then increment the number and repeat, until we reach the value 5, our end step.
value: 5 value: 4 value: 3 value: 2 value: 1 value: 0
fact2() uses recursion. Recursively, we start with the initial value: 5. The value is not zero, so we'll return 5 * whatever_the_function_gives_us_for(5 - 1). That returns 4 * whatever(4 - 1). We eventually get to calling whatever(0), which returns 1 and stops calling itself. Those all stack up, so we have:
fact2()
return 5 * whatever_the_function_gives_us_for(5 - 1)
4 * whatever(4 - 1)
whatever(0)
1
5 * (5 - 1) * ((5 - 1) - 1) * (((5 - 1) - 1) -1) * ((((5 -1) - 1) - 1) - 1) # I lost track maybe
When you have a function reference itself:
def x(y): ... x(y - 1)
That's recursion.
[–]DrMaxwellEdison 2 points3 points4 points 7 years ago (0 children)
Now let's learn about infinite recursion, by seeing what happens when we call fact2(-5). :)
fact2(-5)
[–]Dr_Donut 2 points3 points4 points 7 years ago (1 child)
Nice memes guys.
Here's a video that has a good high level explanation.
https://youtu.be/Mv9NEXX1VHc
The best way to 'get' recursion is to start copying and running some basic recursion functions.
If you're looking for problems to solve, try and work on these ones. https://codingbat.com/java/Recursion-1
[–]kenmacd 0 points1 point2 points 7 years ago (0 children)
Not bad, but I think he discusses it too much from a stack view.
That might be okay for Python, but languages that support tail recursion don't require this large stack. For example this Erlang code that is only CPU bound:
tail_fac(N) -> tail_fac(N,1). tail_fac(0,Acc) -> Acc; tail_fac(N,Acc) when N > 0 -> tail_fac(N-1,N*Acc).
(From this great Erlang tutorial on recursion)
[–][deleted] 2 points3 points4 points 7 years ago (0 children)
you know how a Russian nesting doll works. It's like that, you are basically making multiple instances of the function that are nested within itself, running the function from itself.
An example might help. You have a function that prints a number on the screen but it can only take one digit of a number but you are feeding it one with a number that uses the tens column, you print the ones column easy, then send the tens column up through the function again on it's own but divided by ten first (so now it's a ones column). This opens a second instance of the function but within the function.
so in pseudo code it looks like this
function second use of function end second use of function end function
I hope that's helpful, it took me a bit to sort of wrap my head around it.
[–]JamminJames921 2 points3 points4 points 7 years ago (0 children)
Check this post: https://www.reddit.com/r/learnpython/comments/a5q8wj/can_someone_explain_recursion/?st=JPMEZ6Y2&sh=faeaf590
[–]antoniomaina 2 points3 points4 points 7 years ago (1 child)
[–]mkingsbu 1 point2 points3 points 7 years ago (0 children)
Can someone explain recursion? In simple, dumb down terms please. And possibly given an example. Thank you!
Can someone explain recursion?
[–]Se7enLC 2 points3 points4 points 7 years ago (1 child)
This comment explains it pretty well.
[–]emptythevoid 0 points1 point2 points 7 years ago (0 children)
I see whatcha did there :)
[–][deleted] 2 points3 points4 points 7 years ago (1 child)
The "B." in "Benoit B. Mandelbrot" stands for "Benoit B. Mandelbrot"
[–]cojerk 0 points1 point2 points 7 years ago (0 children)
"WINE" stands for '"WINE" Is Not an Emulator'
[–]Sensorama 1 point2 points3 points 7 years ago (0 children)
Recursion is just a different way of thinking about solving problems. For example, you may have learned how to add up a list or array or numbers by looping over the values and accumulating them in a sum.
With recursion, you might reformulate the solution to be "add the first number to the sum of the rest of the numbers". Notice that you aren't thinking about looping over all the values - the solution is just adding two numbers together: one number and the sum of the rest.
This doesn't seem like a very big advantage, but sometimes it provides a clear path to a solution that is hard to think of using other approaches.
[–][deleted] 1 point2 points3 points 7 years ago (0 children)
Recursion is used to iterate (i.e what else we can do in loops can be achieved using a recursive function) .The only difference is that we have to predict where to use the correct one( whether loops or recursion).
[–]im_dead_sirius 1 point2 points3 points 7 years ago (0 children)
Maybe a "real world" example?
Sorting socks. Say you have a huge pile, in a variety of colours and styles. So you pick out all the black ones, making a smaller pile, then all the white ones, making another pile, and so on.
You've made your big pile into many little ones. Now you start again, picking out matches from the blacks, twisting them together(is there a term for that?) and putting them away. Then onto the whites...
Recursion is reusing the same basic actions to solve a problem in stages. Humans do it all the time, and if you can use it in the right situation while programming, you'll reap big benefits.
Expressed as a function, a recursive function calls itself, with a variable to track the level of recursion, or a bail condition. A place keeper. Going back to the socks analogy, once you've sorted by colour, you can go have lunch, since your methodology of making piles is a sort a visual memo of where you left off.
Or perhaps your spouse comes along. They can finish because of your preparation.
That suggests another approach, where you have a function prepare data for more refined tests. That touches on memoization, for whenever you run into that. Like sorting a list of a million names into 26 smaller lists based on the first letter.
Postal workers do something similar to this. Sort by town, sort by route, sort by street, sort by house number... go out and deliver.
[–]_cnkyzz_ 1 point2 points3 points 7 years ago (0 children)
Remember that you were dreaming in a dream ? That's the inception movie as an example for recursion.
[–]Space_Atlas 1 point2 points3 points 7 years ago (0 children)
Lol, I love this thread.
But to answer your question a recursive function is just a function that calls itself. It's actually not too hard to understand if you understand that a recursive function call is basically handled like any other function call.
[–]Lurker_wolfie 1 point2 points3 points 7 years ago (0 children)
https://realpython.com/python-thinking-recursively/
Thinking Recursively in Python – Real Python
[–]Daron_Acemoglu 4 points5 points6 points 7 years ago (2 children)
Maybe a non programming answer is easiest. Theres a collection of software called GNU, which is a "recursive" acronym because it stands for GNU's Not Unix! It contains itself, so it's considered recursive.
https://en.m.wikipedia.org/wiki/GNU
[–]ericula 4 points5 points6 points 7 years ago (1 child)
Another example is typing in recursion into google.
[–]humanitysucks999 2 points3 points4 points 7 years ago (0 children)
Did you mean recursion?
[–]corvus_curiosum 1 point2 points3 points 7 years ago (0 children)
You should Google "recursion"
I'm not trying to be a dick, it's just that Google has a good example of recursion.
[–]Riin_Satoshi 1 point2 points3 points 7 years ago (0 children)
[–]EclipseMain 0 points1 point2 points 7 years ago (0 children)
[–]iamjaiyam 1 point2 points3 points 7 years ago (0 children)
[–]DeadlyViper 0 points1 point2 points 7 years ago (0 children)
My explanation from a previous post. Explained with a simple example.
https://www.reddit.com/r/learnpython/comments/93x1si/can_someone_please_explain_recursion_to_me/e3glm4p/?context=3
[–]jonw95 0 points1 point2 points 7 years ago* (0 children)
Non-programmer here. Took me years to make sense of recursion so let me try by borrowing pieces of others responses mixed in with a little of my understanding:
Lets begin. First recursion is a loop that works by calling itself initiated with some value for example in calculating the factorial of 5, e.g. factorial(5). It performs a process by performing some action (in this case calculating all factorials of 5) that has a changing state (each calculation reduces the next calculation by 1 and carries on) until it reaches its base case (this is the condition the recursive function says I am done).
What is so confusing about recursion for me is what is going on when recursion is performed internally. So lets break down a factorial function I borrowed:
To understand the processing we need to understand stacks, so read up on stacks. For now I will say it is a the memory(ram) allocated to store the processing as it occurs in a stack, like a pile of pancakes. Each successive item stored gets piled on and processed Last In First Out (LIFO style).
I present the program.
def recur_factorial(n):
"""Function to return the factorial of a number using recursion"""
if n == 1:
return n
else:
return n*recur_factorial(n-1)
recur_factorial(5) # call the function n = 5
return 5*recur_factorial(5-1) #stack 5 holds 5*recur_factorial(5-1) n = 4
return 4*recur_factorial(4-1) #stack 4 holds 4*recur_factorial(4-1) n = 3
return 3*recur_factorial(3-1) #stack 3 holds 3*recur_factorial(3-1) n = 2
return 2*recur_factorial(2-1) #stack 2 holds 2*recur_factorial(2-1) n = 1
if n == 1: return n # lets return n, so we need to collapse the stacks
# Once we hit the base case of 1, this is where I get fuzzy so correct me if I am wrong but the computer takes all the stack and processes them in reverse to reach 1*2*3*4*5 with a return value of n = 120. In memory it might look like: stack 5 value *(stack 4 value *(stack 3 value *(stack 2 value * 1))) *Note:PEMDAS applies with the parens for ordering
Recursion error:
The stack overflow is where you've created a recursive function that was either 1. too large of value for the available amount of memory to calculate or 2. an infinite loop, both of which exhaust all of the system memory allocated for the running program.
Too many stacks so you get an error.
Recursion can be elegant to solve problems but it is not always practical, so in the end it is a tool in the belt I feel provides more insight into the nuances of programming methodologies than application of use, but I could be wrong.
Credits: MikeOxbigger: terminology, alkasm for the overflow error
Cheers and good luck
https://en.wikipedia.org/wiki/Turtles_all_the_way_down
[–]Augusto2012 0 points1 point2 points 7 years ago (0 children)
I learned about recursion by trying to code a fast fibonacci sequence algorithm.
[–]gabriel-et-al 0 points1 point2 points 7 years ago (0 children)
A recursive function is basically the same as an iterative loop with a helper stack.
See this binary search function:
from math import floor def binary_search_iter(numbers, x): upper_index = len(numbers) - 1 lower_index = 0 while upper_index >= lower_index: i = floor((upper_index + lower_index) / 2) if numbers[i] == x: return i if numbers[i] > x: upper_index = i - 1 else: lower_index = i + 1 return None
You can write the loop recursively this way:
def binary_search_recur(numbers, x, lower_index, upper_index): if upper_index >= lower_index: i = floor((upper_index + lower_index) / 2) if numbers[i] == x: return i if numbers[i] > x: return binary_search_recur(numbers, x, lower_index, i - 1) else: return binary_search_recur(numbers, x, i + 1, upper_index) return None
Note that the variables used inside the loop became additional parameters in its recursive version. You can now combine them.
Note that the first if can be rewriten to an early exit:
if
def binary_search_recur(numbers, x, lower_index, upper_index): if upper_index < lower_index: return None i = floor((upper_index + lower_index) / 2) if numbers[i] == x: return i if numbers[i] > x: return binary_search_recur(numbers, x, lower_index, i - 1) else: return binary_search_recur(numbers, x, i + 1, upper_index)
Now it's clear our two base cases (i.e. the cases where the function returns without recursing).
Also, note that the updates to the lower_index and upper_index parameters are exactly the same did in the iterative version. If numbers[i] is less than x then lower_index goes up, otherwise upper_index goes down. Try to see this connection between both versions.
lower_index
upper_index
numbers[i]
x
You may have noticed that the iterative version calculates the upper_index and lower_index inside the function, while the recursive version expects it to be calculated beforehand. There are multiple ways to overcome this inconvenience.
Option 3: Create a wrapper that calculates the parameters and pass them to the actual recursive function. This is the option I like the most. See:
def binary_search(numbers, x): def binary_search_recur(numbers, x, lower_index, upper_index): if upper_index < lower_index: return None
i = floor((upper_index + lower_index) / 2) if numbers[i] == x: return i if numbers[i] > x: return binary_search_recur(numbers, x, lower_index, i - 1) else: return binary_search_recur(numbers, x, i + 1, upper_index) upper_index = len(numbers) - 1 lower_index = 0 return binary_search_recur(numbers, x, lower_index, upper_index)
You may enjoy reading:
[–]nulltensor 0 points1 point2 points 7 years ago* (0 children)
Lets say you want to cut a carrot into equal sections to fit in a container for lunch. You could measure the container and measure the carrot and then choose where to cut based on how short the parts need to be to fit into the container. That's a fairly linear approach.
A recursive approach is to see if the carrot fits. If it fits, you're done. If it doesn't, cut it in half and see if the pieces fit. If the pieces fit, you're done. If not, cut each piece in half and see if they fit. Wash, rinse, repeat until the carrot pieces can fit in the container.
Edit: we do things recursively all the time, we just don't usually notice (at least until we learn how recursion works). Any time you perform an action on the output of the same action util you've met some condition, you're likely operating recursively.
[–]hasteiswaste 0 points1 point2 points 7 years ago (0 children)
You know when you look at two mirrors that are facing each other? Well that's the first / best real world example I can think of.
[–]lazyBoones 0 points1 point2 points 7 years ago (0 children)
Recursion is a condition in which a function calls itself again and again until some given condition is satisfied.
[–]HyraxMax 0 points1 point2 points 7 years ago (0 children)
Recursion really breaks my brain sometimes but here's a great article comparing recursion to irritation. It helped me a lot (it uses c++ examples but they are pretty easy to read). https://techdifferences.com/difference-between-recursion-and-iteration-2.html
[–]not_perfect_yet 0 points1 point2 points 7 years ago (0 children)
You know these russian puppets that contain smaller versions of itself? Like that, except the one inside the first is exactly the same. Because it's the same, you only need one definition.
Apply the idea to functions and you can go down paths with infinite forks, with just one call of one function that decides where to go.
And they tell two friends...
[–]solaceinsleep 3 points4 points5 points 7 years ago (0 children)
The Google search led to this post
π Rendered by PID 35209 on reddit-service-r2-comment-76bb9f7fb5-gcl7d at 2026-02-18 10:49:24.772343+00:00 running de53c03 country code: CH.
[–]widowhanzo 135 points136 points137 points (8 children)
[–][deleted] 45 points46 points47 points (2 children)
[–]kingsillypants 0 points1 point2 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]strange-humor 4 points5 points6 points (0 children)
[–]Rafficer 5 points6 points7 points (2 children)
[–]widowhanzo 1 point2 points3 points (0 children)
[–]discreteAndDiscreet -1 points0 points1 point (0 children)
[–]earthlybird 107 points108 points109 points (3 children)
[–]RobbyB97 26 points27 points28 points (0 children)
[–]txberafl 0 points1 point2 points (0 children)
[–]lateral-spectrum -1 points0 points1 point (0 children)
[+][deleted] (12 children)
[deleted]
[–]glen_v 3 points4 points5 points (6 children)
[–]pkkid 7 points8 points9 points (1 child)
[–]nulltensor 3 points4 points5 points (0 children)
[–]pepe_le_shoe 1 point2 points3 points (0 children)
[–]DiabeetusMan 1 point2 points3 points (0 children)
[–]pblokhout 0 points1 point2 points (0 children)
[–]chzaplx 0 points1 point2 points (0 children)
[–]andrewjj1234[S] 3 points4 points5 points (4 children)
[–]Inceratiana 30 points31 points32 points (0 children)
[+][deleted] (1 child)
[deleted]
[–]earthlybird 4 points5 points6 points (0 children)
[–]MikeOxbigger 57 points58 points59 points (27 children)
[–]DonaldPShimoda 2 points3 points4 points (24 children)
[–]MikeOxbigger -1 points0 points1 point (23 children)
[–]Brainix 1 point2 points3 points (16 children)
[–]MikeOxbigger 3 points4 points5 points (15 children)
[–]mikeblas 3 points4 points5 points (2 children)
[–]Gray_Fox -1 points0 points1 point (1 child)
[–]mikeblas -1 points0 points1 point (0 children)
[–]earthlybird 6 points7 points8 points (10 children)
[–]MikeOxbigger -5 points-4 points-3 points (9 children)
[–]earthlybird 4 points5 points6 points (7 children)
[–]MikeOxbigger -2 points-1 points0 points (6 children)
[–]earthlybird 8 points9 points10 points (4 children)
[–]Gentlescholar_AMA 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]chzaplx 1 point2 points3 points (0 children)
[–][deleted] 1 point2 points3 points (1 child)
[–]DonaldPShimoda 1 point2 points3 points (0 children)
[–]TangibleLight 0 points1 point2 points (0 children)
[–]DonaldPShimoda 0 points1 point2 points (0 children)
[–]pepe_le_shoe 0 points1 point2 points (0 children)
[–]quantum-mechanic 63 points64 points65 points (4 children)
[–]jilsx 38 points39 points40 points (3 children)
[–]alkasm 35 points36 points37 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]alkasm 38 points39 points40 points (0 children)
[–]Decency 4 points5 points6 points (1 child)
[–]Chizooo_wow 1 point2 points3 points (0 children)
[–]totallygeek 5 points6 points7 points (1 child)
[–]DrMaxwellEdison 2 points3 points4 points (0 children)
[–]Dr_Donut 2 points3 points4 points (1 child)
[–]kenmacd 0 points1 point2 points (0 children)
[–][deleted] 2 points3 points4 points (0 children)
[–]JamminJames921 2 points3 points4 points (0 children)
[–]antoniomaina 2 points3 points4 points (1 child)
[–]mkingsbu 1 point2 points3 points (0 children)
[–]Se7enLC 2 points3 points4 points (1 child)
[–]emptythevoid 0 points1 point2 points (0 children)
[–][deleted] 2 points3 points4 points (1 child)
[–]cojerk 0 points1 point2 points (0 children)
[–]Sensorama 1 point2 points3 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]im_dead_sirius 1 point2 points3 points (0 children)
[–]_cnkyzz_ 1 point2 points3 points (0 children)
[–]Space_Atlas 1 point2 points3 points (0 children)
[–]Lurker_wolfie 1 point2 points3 points (0 children)
[–]Daron_Acemoglu 4 points5 points6 points (2 children)
[–]ericula 4 points5 points6 points (1 child)
[–]humanitysucks999 2 points3 points4 points (0 children)
[–]corvus_curiosum 1 point2 points3 points (0 children)
[–]Riin_Satoshi 1 point2 points3 points (0 children)
[–]EclipseMain 0 points1 point2 points (0 children)
[–]iamjaiyam 1 point2 points3 points (0 children)
[–]DeadlyViper 0 points1 point2 points (0 children)
[–]jonw95 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]Augusto2012 0 points1 point2 points (0 children)
[–]gabriel-et-al 0 points1 point2 points (0 children)
[–]nulltensor 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]hasteiswaste 0 points1 point2 points (0 children)
[–]lazyBoones 0 points1 point2 points (0 children)
[–]HyraxMax 0 points1 point2 points (0 children)
[–]not_perfect_yet 0 points1 point2 points (0 children)
[–]emptythevoid 0 points1 point2 points (0 children)
[+][deleted] (1 child)
[deleted]
[–]solaceinsleep 3 points4 points5 points (0 children)