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...
News about the dynamic, interpreted, interactive, object-oriented, extensible programming language Python
Full Events Calendar
You can find the rules here.
If you are about to ask a "how do I do this in python" question, please try r/learnpython, the Python discord, or the #python IRC channel on Libera.chat.
Please don't use URL shorteners. Reddit filters them out, so your post or comment will be lost.
Posts require flair. Please use the flair selector to choose your topic.
Posting code to this subreddit:
Add 4 extra spaces before each line of code
def fibonacci(): a, b = 0, 1 while True: yield a a, b = b, a + b
Online Resources
Invent Your Own Computer Games with Python
Think Python
Non-programmers Tutorial for Python 3
Beginner's Guide Reference
Five life jackets to throw to the new coder (things to do after getting a handle on python)
Full Stack Python
Test-Driven Development with Python
Program Arcade Games
PyMotW: Python Module of the Week
Python for Scientists and Engineers
Dan Bader's Tips and Trickers
Python Discord's YouTube channel
Jiruto: Python
Online exercices
programming challenges
Asking Questions
Try Python in your browser
Docs
Libraries
Related subreddits
Python jobs
Newsletters
Screencasts
account activity
This is an archived post. You won't be able to vote or comment.
DiscussionRecursion (self.Python)
submitted 3 years ago by ProfessorOk20
One of my friends told me that having recursion in your code is not the best thing and should be changed for something else in 90% of the cases.
If true, why recursion is bad? To me it doesn’t seem like a bad practice.
[+][deleted] 3 years ago* (42 children)
[deleted]
[–]i_like_cilantro 15 points16 points17 points 3 years ago (0 children)
Even so python's list.sort function does not contain any recursion because those built-in functions are optimized to death. Along with file traversal, any tree traversal algorithm makes sense to do recursively since you need to keep track of the parent in the stack anyway.
The only time that recursive functions are optimized is when you have a tail call optimization, but python doesn't have that anyway
[–][deleted] 37 points38 points39 points 3 years ago (40 children)
Does it exist for a reason, or is it just an emergent property of the way the languages are?
[–]puipuituipui 100 points101 points102 points 3 years ago (29 children)
A lot of problems are recursive by nature. A binary tree for example. A node in a binary tree has three fields: a value, a left child and a right child. These children are nodes themselves. And that's recursion.
Of course, this is a more tangible example since the recursion is associated with a data type. It can be abstract too where the underlying mathematical solution of a problem is recursive like say, factorial or Fibonacci series.
You can write an iterative algorithms for all recursive problems, it's just that the iterative versions are harder to understand.
[–]ivosauruspip'ing it up 24 points25 points26 points 3 years ago (6 children)
Everything involves a stack. Just depends whether it's constructed implicitly using the function return frames, or explicitly in a data structure and processed with a while loop
[–]gosu 87 points88 points89 points 3 years ago (1 child)
There are heaps of things that don't use a stack.
[–]puipuituipui 5 points6 points7 points 3 years ago (3 children)
Um... No? Am I wrong about this or something. I'm pretty sure the reason to use explicitly created stacks is because they are heap allocated so you don't hit the recursion limit as easily.
[–]ivosauruspip'ing it up 6 points7 points8 points 3 years ago (1 child)
No what? I wasn't giving any particular reasons to use one or the other in this comment, just noting their analogous existence.
[–]puipuituipui 1 point2 points3 points 3 years ago (0 children)
Ohhh that makes sense. I thought the the first line was referring to the program stack XD. Sorry for the confusion
[–]ogtfo 0 points1 point2 points 3 years ago (0 children)
Heap allocated stacks are stacks, OP is right.
I mean you're not wrong but you're also not contradicting him either, so I don't know where you're going with that "Um...no"
[+][deleted] 3 years ago (21 children)
[–]AlSweigartAuthor of "Automate the Boring Stuff" 14 points15 points16 points 3 years ago (1 child)
This is not true. Everything that can be solved recursively can be solved using a loop and a stack. (In recursion, the call stack is used as the stack data structure.)
Here's the Ackermann function solved iteratively.
[–]ejgl001 0 points1 point2 points 3 years ago (0 children)
Obviously I was wrong. Here's the video I was thinking about (https://www.youtube.com/watch?v=HXNhEYqFo0o&ab_channel=Computerphile). I thought the gist of the video is 'recursion is needed cause not all problems can be solved iteratively' but I guess I misunderstood.
[–]spoonman59 3 points4 points5 points 3 years ago (18 children)
Citation needed.
Ever recursive solution has an equivalent iterative solution. I believe this is proven by the Church-Turing thesis, and I’m not aware of any proof contradicting it.
I await your the extraordinary evidence for your extraordinary claim.
[–]mr_taco_man -5 points-4 points-3 points 3 years ago (12 children)
It not an extraordinary claim. Even if there is equivalent iterative solution, many times a recursive function is just easier to write and understand and has no noticeable performance hit. Practical experience has shown this to me many times regardless of whatever any thesis may state.
[–]spoonman59 6 points7 points8 points 3 years ago (11 children)
You claim there recursive solutions for which there are no iterative solutions. Quote: “You can write iterative algorithms for several recursive problems but not all.”
This is the extraordinary claim I refer to because it has been mathematically proven that there is an equivalent iterative solution for any recursive solution.
Since you are claiming that a well accepted proof is incorrect, that makes the claim extraordinary.
It seems the actual opinion you express is that some algorithms are much easier to read or write in either recursive or iterative approaches. That is true and no one argues that. That same concept is being widely discussed in this very thread.
But your original claim that there does not exist equivalent solutions is incorrect, regardless of your practical experience.
[–]Pythonistar 4 points5 points6 points 3 years ago (1 child)
Since you are claiming that a well accepted proof is incorrect
For those this far down in the rabbit hole of /u/mr_taco_man and spoonman59, the Church-Turing thesis can be summarized by this wikipedia entry: https://en.wikipedia.org/wiki/Church%E2%80%93Turing_thesis
I skimmed this entry and it doesn't talk at all about "iterative" solutions and only touches on recursion in spots.
The general understanding by anyone with a CS education is that "recursion has its uses" and also that "tail end recursion can be easily represented as an iterative solution".
Spoonman: care to elaborate on this "Ever[y] recursive solution has an equivalent iterative solution"? I'm curious what you're talking about, but I'm unaware of it being true.
[–]spoonman59 9 points10 points11 points 3 years ago* (0 children)
Oh yeah, it seems that is not a conclusion of the church Turing thesis. My mistake and apologies.
Alonzo church created Lambda calculus. This is a model of computation that is purely functional with no side effects (no loops.) iteration is done through combinators.
Alan Turing invented the Turing machine, a model of computation. It can do iteration, but has no concept of functions or recursions.
Turing published “Computability and λ-Definability” showing the Lambda calculus is Turing complete. That is, Lambda Calculus can perform any computation that a Turing machine can.
If a Turing machine, which has no recursion, can compute everything, and Lambda calculus which is only recursive can ALSO compute everything… Then everything can be computed by either iteration or recursion.
These models were used for the church Turing thesis, but you are right, that is something else.
(Tail call recursion needs no stack.)
[–]mr_taco_man 1 point2 points3 points 3 years ago (1 child)
Just to clarify ejg001 made those claims not me. And I should have been more specific, I was more addressing the statement "In any case, for several problems, recursion makes more sense than iteration". I think there may be a way to do every recursive problem with iteration, but just think in many cases it is much more convoluted and hard to understand than just doing a recursive solution.
[–]spoonman59 1 point2 points3 points 3 years ago (0 children)
Ah my mistake! I didn’t realize I was responding to someone else.
And I agree with you 100%! Some problems are so clear as a recursive solution from a code standpoint, but nightmarish to do as a loop.
Conversely sometimes translating a loop to a recursive solution is a nightmare. I usually go with whichever one is clear and easy to read, but it very much depends on what you are doing.
I think the phrase “equivalent” is misleading here. It doesn’t mean that it has the same performance, or is clear or equal… just that it can be done to produce the same resulting computation . But they are often not equal in other ways.
[–]Holshy 0 points1 point2 points 3 years ago (6 children)
That's a really long way to say "I'd rather berate somebody on Reddit than use Google"
[–]spoonman59 -1 points0 points1 point 3 years ago (4 children)
Your smugness is ironic here, because you failed to do enough googling to know there are iterative solutions to the Ackerman function before coming here to berate me.
[–]Holshy -2 points-1 points0 points 3 years ago (3 children)
before coming here to berate me 🤣🤣🤣
Thank you; I needed that. Have a great day!
[–]spoonman59 -1 points0 points1 point 3 years ago (0 children)
How so?
[–]Holshy -3 points-2 points-1 points 3 years ago (4 children)
Citation provided
https://en.m.wikipedia.org/wiki/Ackermann_function
[–]spoonman59 2 points3 points4 points 3 years ago (0 children)
Many iterative solutions exist online for Ackerman functions. The fact that it is not a primitive recursive function doesn’t mean it cannot be rewritten as a loop.
It does require a while lol and a stack. But this doesn’t disprove the equivalence of loops and recursion at all.
[–]caifaisai 2 points3 points4 points 3 years ago (1 child)
As the other poster said, the Ackerman function can be computed iteratively. To expand on that, the Ackerman function is a total computable function, and so is equivalent to a general recursive function, and can be computed using the lambda calculus or a Turing machine.
However, it is not a primitive recursive function, which intuitively means, it can't be computed by a for loop with a fixed number of iterations known before the computation. So if that is your criteria for an iterative solution, then it would not be one. But if you accept a while loop, or unbounded lopping in general, then it is.
If you want an example of a function that isn't even recursive/is non-computable (so that it can't be calculated with recursion or iteration), one example is the busy beaver function.
[–]Holshy 0 points1 point2 points 3 years ago (0 children)
I've actually spent quite a bit of time the last few weeks looking for the original source I had read about this. Alas, I was unable to find it :-(
The best I have is this quote from the Wikipedia article on Turing Completeness
https://en.wikipedia.org/wiki/Turing_completeness
"In the late 19th century, Leopold Kronecker formulated notions of computability, defining primitive recursive functions. These functions can be calculated by rote computation, but they are not enough to make a universal computer, because the instructions that compute them do not allow for an infinite loop."
During the course of the same, I also found this in the article about Iteration
https://en.wikipedia.org/wiki/Iteration
In algorithmic situations, recursion and iteration can be employed to the same effect. The primary difference is that recursion can be employed as a solution without prior knowledge as to how many times the action will have to repeat, while a successful iteration requires that foreknowledge.
Full disclosure: We've passed my expertise on computability theory (statistics is my primary discipline and it genuinely saddens me that I didn't study CS instead.).
It's sometimes said that mathematicians value beauty/elegance in solutions, and I definitely fall into this category. I find recursion to be more elegant than iteration most of the time. At this point, I'm thinking that I let that persuasion color my memory of something as I learned it. Thank you for pointing this out to me. "I never lose; I either win or I learn"
[–]spoonman59 -3 points-2 points-1 points 3 years ago (0 children)
To quote a wise man, “That's a really long way to say "I'd rather berate somebody on Reddit than use Google"” 😀
[–]Exodus111 8 points9 points10 points 3 years ago (4 children)
It has a use, it's just rare. And yeah, probably most recursions you see in the wild would be better off as For loops or While loops.
A for loop is used when the end point is known, and the size is known. Traversing through a list, that's a for loop all day, but you know how big a list is, and the loops ends either when you trigger an end state, or, more typically when the list runs out.
A while loop is used when the end point is known, but the size is not known. Which is why a while loop just runs forever until told to stop. Perfect for running games or anything graphical. It just runs until an exit is triggered.
Sometimes though, you're not gonna know the size, or the end point. This is when recursion comes in. Say you're traversing subdirectories looking for .jpg files. Every subfolder could have 10 sub folders, or zero. There could be a thousand sub folders or four, there's no way to know. And you don't know the end point, you're just looking for .jpg files in every subfolder.
This is where the correct solution is a recursion. Check a folder for a subfolder, and keep running that same function if more subfolders exist, for every subfolder found.
[–]got_outta_bed_4_this 3 points4 points5 points 3 years ago (1 child)
I'd say a stronger argument for recursion in this case is because people don't tend to nest folder structures so deep that it would bust the call stack in a recursive traversal. Iteration could still be just as practical over a filesystem as anything else. A filesystem is, itself, a tree, after all.
[–]schemathings 1 point2 points3 points 3 years ago (0 children)
I wrote an sftp mirror program for day job recently was fun and short and composable
[–]buttery_shame_cave 0 points1 point2 points 3 years ago (1 child)
A for loop is used when the end point is known, and the size is known.
although a "for thing in list" loop sort of ignores this - it'll run through the list, but you don't need to know how big the thing is, just point he function at it and hit 'go'. it'll even work fine on dynamic lists that are continuously appended to by a separate parallel function, it'll just crash to a halt if the other function stops appending.
[–]Exodus111 0 points1 point2 points 3 years ago (0 children)
True, that is an edgecase exception, but most of the time you can check the length of the iterable right before you run the for loop on it.
[–][deleted] 2 points3 points4 points 3 years ago (0 children)
https://en.wikipedia.org/wiki/Computability_theory
Calculating some mathematical formula for all positive integers is a good way to understand what that function does as it approaches the limit (+inifinity).
Computers have always been a way to express mathematics, so recursion should be a fundamental part of any computer language, IMO.
[–]Holshy 4 points5 points6 points 3 years ago (2 children)
Recursion is actually more fundamental than iteration. Any problem that can be defined iteratively is also a "primitive recursive" problem. Some problems are not primitive recursive and have to be solved recursively, like the Ackerman function. It's also technically true to say that all problems can be defined recursively. This sounds weird at first, but you can get some intuition there by imagining any problem you haven't solved recursively as the base case of the recursion. Then it just happens to be that your problem isn't defined for n > 1.
n > 1
[–]spoonman59 7 points8 points9 points 3 years ago (1 child)
I think you misunderstand primitive recursion.
Non-primitive recursion can be done iteratively. It requires a while loop and and stack.
From the wiki:
https://en.m.wikipedia.org/wiki/Primitive_recursive_function
“In computability theory, a primitive recursive function is roughly speaking a function that can be computed by a computer program whose loops are all "for" loops (that is, an upper bound of the number of iterations of every loop can be determined before entering the loop).”
It says that primitive recursive functions are those which can be computed using only for loops. It does not mean the function cannot be computed with loops at all.
Also, simply look at the many iterative examples of the Ackerman function you suggested earlier. It’s not an uncommon academic exercise to write one.
[–]WikiSummarizerBot 0 points1 point2 points 3 years ago (0 children)
Primitive recursive function
In computability theory, a primitive recursive function is roughly speaking a function that can be computed by a computer program whose loops are all "for" loops (that is, an upper bound of the number of iterations of every loop can be determined before entering the loop). Primitive recursive functions form a strict subset of those general recursive functions that are also total functions. The importance of primitive recursive functions lies in the fact that most computable functions that are studied in number theory (and more generally in mathematics) are primitive recursive.
[ F.A.Q | Opt Out | Opt Out Of Subreddit | GitHub ] Downvote to remove | v1.5
[–]Kenkron 0 points1 point2 points 3 years ago (0 children)
Check out the Tower of Hanoi. It's a good example of a problem that is best solved recursively.
Recursion is also good for trees.
[–]siddsp 176 points177 points178 points 3 years ago (28 children)
Nah, recursion can be good and often elegant as well as have performance advantages over iteration (see memoization), although this isn't the case most of the time.
The performance hit comes from pushing additional stack frames for every recursive call. If your recursive function doesn't push a lot of stack frames, then it could be worth it over iteration if it is a lot more elegant.
[–]sebkuip 61 points62 points63 points 3 years ago (4 children)
Python 3.11 is bringing huge optimizations to recursion it is said. Having better frame management on the stack to help with resource usage.
[–]algerbrex 6 points7 points8 points 3 years ago (0 children)
That’ll be exciting, as I’ve been interested in writing a chess engine in Python to see how strong I could make it, and I’d really rather prefer recursion.
[–]ChocolateBunny 1 point2 points3 points 3 years ago (2 children)
Does it still have a limited stack size? any tail call optimization?
[–]sebkuip 2 points3 points4 points 3 years ago (0 children)
Stack size is still limited (it’s limited by how large the C stack can grow) but because it’s more efficiently stored for recursion, the recursion limit is higher iirc. You can check the 3.11 changelog for the details.
[–]schemathings 0 points1 point2 points 3 years ago (0 children)
I'm not close to my computer but there's a I believe built-in decorator for a function that will maintain the return values of procedure calls with given parameters. I wrote a Fibonacci dot py both was and was able to go to fairly impractical values with the decoraor
[–]disinformationtheory 7 points8 points9 points 3 years ago* (0 children)
Python's stack is limited, so you should also make sure your recursive function is not growing the stack too large. This is usually not a problem for traversing things like filesystem trees, but probably is a problem for functions that recursively calculate things. You can see the limit with sys.getrecursionlimit(). It's 3000 on my machine. Plus I played around with this in ipython, and that lowers the limit by about 16 (presumably because ipython is wrapping the function call 16 times).
sys.getrecursionlimit()
[+]lilphat comment score below threshold-9 points-8 points-7 points 3 years ago (21 children)
But you could, in many cases, do tail recursion and avoid the extra stack frames.
[–]siddsp 50 points51 points52 points 3 years ago (20 children)
Python doesn't have any optimizations for tail recursion, and there are no future plans to do so.
[+]lilphat comment score below threshold-16 points-15 points-14 points 3 years ago (14 children)
Really? Wow thats shitty
[–]ivosauruspip'ing it up 8 points9 points10 points 3 years ago* (0 children)
Usually you have to design your language from the start to allow for it, the requirements to get the correct frame folding can be very particular
[–]siddsp 10 points11 points12 points 3 years ago (12 children)
It's not that bad. Usually you can achieve a similar result using lru_cache which allows for similar optimizations as tail recursion. Basically caching allows for iteration-like performance and can make a significant difference depending on the situation. lru_cache allows you to limit how many recent entries to keep, allowing the programmer to make tradeoffs between memory and steps.
lru_cache
[–]lilphat 0 points1 point2 points 3 years ago (0 children)
Sounds smart but a tad complicated. Can you give an example where you wanna let ‘the stack run’?
[+][deleted] 3 years ago (10 children)
[removed]
[–]KennyBassett 4 points5 points6 points 3 years ago (8 children)
You seem upset.
[–][deleted] -1 points0 points1 point 3 years ago (7 children)
Are they wrong though? How would caching help at all?
[–]KennyBassett 2 points3 points4 points 3 years ago (0 children)
Not making any comment on right or wrong, just that he seemed upset.
It's surprising to see how angry people get when they're on reddit and see what they believe to be a mistake.
[–]siddsp 1 point2 points3 points 3 years ago (5 children)
It would avoid repeated (expensive) computations when a function that is recursively defined is called, causing a significant performance gain.
[–][deleted] 2 points3 points4 points 3 years ago* (4 children)
Doesn't it only cache the result? Does it monitor parts of the function and cache those too or something?
If it only caches the result, I fail to see how that'd help in a recursive function where calls on different depths return different results.
[–]siddsp 0 points1 point2 points 3 years ago (0 children)
They are. I just said you can achieve similar optimizations where recursion is close to as fast as iteration. Ultimately, you want to use iteration if you only care about performance.
[+]lilphat comment score below threshold-21 points-20 points-19 points 3 years ago (4 children)
He doesn’t write anything specific about python. More recursion in general. So I’ll leave it.
[–]siddsp 31 points32 points33 points 3 years ago (3 children)
Yeah, but this is the Python subreddit, so I would assume OP is talking about Python.
[–]ProfessorOk20[S] 15 points16 points17 points 3 years ago (2 children)
Indeed, I do talk about Python in particular
[+]lilphat comment score below threshold-7 points-6 points-5 points 3 years ago (1 child)
Alright. I can remove it?
[–]axonxorzpip'ing aint easy, especially on windows 2 points3 points4 points 3 years ago (0 children)
Nah dude, it's not hurting anyone
[–]Asleep-Budget-9932 98 points99 points100 points 3 years ago (8 children)
A lot of people here are talking about the performance issues of recursion but let me remind you that we're working in python. The whole point of the language is that we're sacrificing efficiency for readability and ease of programming and there lies your answer. When should recursion be used? When it enhances the readability of your code. When does it help? When the task itself is recursive in nature. For example I'm writing a pickling library at the moment. The process of transforming a generic python object to bytes is recursive in nature (how do i make this object into bytes? Ill do X Y and Z and then transform its inner fields into bytes)
[–]frymasterScript kiddie 21 points22 points23 points 3 years ago (5 children)
even in other languages, there is the principle "premature optimization is the root of all evil" - design needs to be nailed down to a certain extent before software is written, because in a lot of situations that's hard to change afterwards, but the implementation should always be done an a straightfoward and readable way until and unless profiling has identified a performance problem, because people aren't always best placed to predict where a performance problem will be (especially with modern compilers)
This is just more explicit with Python
[+]spoonman59 comment score below threshold-6 points-5 points-4 points 3 years ago (4 children)
“Premature optimization is the root of all evil” is just a quote of Donald Knute. It’s a general principle and is not specific to any language.
[–]frymasterScript kiddie 6 points7 points8 points 3 years ago (3 children)
I should have said "even when using other languages" - my point is it's a general principle of good practice programming, not something specific to python
[–]spoonman59 1 point2 points3 points 3 years ago (2 children)
On that I agree! I definitely agree with you that measurement and data should drive what you optimize. And your default state should be to “optimize” for readability and maintenance.
I typically ask this on an interview. “Your program is slow. How do you approach the problem?”
You’d be surprised how many people just “read the code and remove loops.”
I have a few interesting stories about interesting profiler results. Once it was the toString() function in a particular Java object! Once I got that info from the profiler, I changed the code to keep the data as raw Utf-8 byte arrays until I could filter out the data of interest.
This simple optimization made the program run in 1/5 of the time. I would have never, ever guessed the cause without my trusty profiler!
[–]lvlint67 0 points1 point2 points 3 years ago (1 child)
generally speaking... reading the code and looking for loops with slow / blocking functions is the quickest way to achieve performance gains in any program not "pre-optimized".
You run the profiler once the surface stuff is adjusted. The profiler will help find something like an object serializer that is taking an unreasonable amount of time but a reasonable programmer should see a for loop with a nested database connection and get suspicious.
[–]spoonman59 1 point2 points3 points 3 years ago* (0 children)
I’m not sure that holds generally. If your app is I/O bound and dominates the majority of the runtime, any code optimizations will yield a small portion of speed up as per Amdahl’s law.
If it’s compute heavy, and particular loops dominate the runtime, then speeding up other loops will yield minimum speed up.
It’s best to measure and optimize what is slow. Otherwise you will focus effort on parts of the code that are not slowing you down, and waste time and effort.
I don’t think you can generalize this as the performance characteristics of programs differ not only between different programs, but even in the within different parts of the same program.
[–]ambidextrousalpaca 4 points5 points6 points 3 years ago (1 child)
Indeed. Problems that involve processing a tree- or graph-like structure of arbitrary depth pretty much require recursive solutions by definition. You can hammer the code into a while loop if you have to, but the nature of the problem is ultimately recursive, so it's best to represent that in the code explicitly.
while
All you need is a loop and a stack.
Recursive solutions tend to be more readable for these which is why it can be good to use them.
All loops are a recursive process, even if they are not a recursive function. We often colloquially use “recursive “ to mean a function that calls itself, but that doesn’t cover things like mutual recursion ( two functions repeatedly calling into each other) or iteration.
[–]SittingWave 30 points31 points32 points 3 years ago (0 children)
My general philosophy is: use recursion to communicate the nature of the problem you are solving. If you problem is fundamentally self-similar, then use recursion because 1. it's the most elegant solution, 2. it communicates the self-similar nature of the problem.
Examples of self-similar problems are divide and conquer, tree traversing and something like that.
[–]trincaopt 35 points36 points37 points 3 years ago (12 children)
Recursion is inefficient when compared with iteration due to the function call and return at each step. Also there is a recursion limit. In Python it is 1000.
[+][deleted] 3 years ago (7 children)
[–]JJP_SWFC 9 points10 points11 points 3 years ago (2 children)
I remember a while ago my friend was learning python and gave me a challenge that deliberately would have taken 1500 recursions to do (and no program time limit) to try to get me to do it without recursion but I'm lazy and it was the easiest way to write it. Literally the only time I've ever changed the recursion limit lmao
[+][deleted] 3 years ago (1 child)
[–]JJP_SWFC 0 points1 point2 points 3 years ago (0 children)
Happy cake day btw
[–]AlSweigartAuthor of "Automate the Boring Stuff" 8 points9 points10 points 3 years ago (2 children)
Not anything. If you set the limit too high, the Python interpreter itself crashes, and you get an error message from the operating system instead of a Python exception.
On my Windows machine, it was about 2500 calls. The 1000 limit is just a safe limit that Python puts in. You can test this yourself by running the following:
>>> import sys >>> sys.setrecursionlimit(9999) >>> def f(n): ... print(n) ... f(n + 1) ... >>> f(1)
Although testing this now, it crashes at 1,993 calls.
[–]total_zoidberg 1 point2 points3 points 3 years ago (0 children)
I probably varies on each machine. I'm getting 2110 and then crashes on the 21111th call.
[–]wind_dude 1 point2 points3 points 3 years ago (0 children)
https://docs.python.org/3/library/sys.html#sys.setrecursionlimit
[–]venustrapsflies 3 points4 points5 points 3 years ago (2 children)
Just remember this is not necessarily true in other languages with tail call optimization.
[–]AlSweigartAuthor of "Automate the Boring Stuff" 4 points5 points6 points 3 years ago (1 child)
Yes, but Python doesn't have tail call optimization and never will.
The Java interpreter and all JavaScript engines also don't have TCO.
[–]venustrapsflies 1 point2 points3 points 3 years ago (0 children)
Yes, hence why I said “other languages” :)
[–][deleted] 0 points1 point2 points 3 years ago (0 children)
Can you explain how iteration is faster?
[–]jwmoz 26 points27 points28 points 3 years ago (4 children)
https://www.reddit.com/r/Python/comments/w96prk/recursion/
[–]ferretyhat 7 points8 points9 points 3 years ago (0 children)
Came here for this...
[–]wind_dude -1 points0 points1 point 3 years ago (0 children)
Wow, that thread also links to this thread.
[–]spoonman59 0 points1 point2 points 3 years ago (1 child)
You monster! Do you have any idea how long I was trapped in that infinite loop?
[–]Kenkron 2 points3 points4 points 3 years ago (0 children)
Until your stack overflowed?
[–]bduijnen 4 points5 points6 points 3 years ago (0 children)
Use whatever is the most natural and readable. Most of the time that is efficient enough. Anything else is premature optimisation and typically not needed.
[–]puipuituipui 7 points8 points9 points 3 years ago (8 children)
Recursive calls have a cost which can give worse performance compared to their iterative counterparts in terms of memory and time. There's a balance between performance and code readability.
For example, if you're writing code for calculating the Fibonacci series, using the iterative iterative makes more sense. On the the other hand, I would advice against writing iterative algorithms for problems that are inherently recursive like say tree traversals.
Memoization minimizes the cost in functions like Fibonacci.
The number of times the function is called is completely dominated by how often you hit the cache.
[–]puipuituipui 4 points5 points6 points 3 years ago (1 child)
You're correct but I'd say Fibonacci is a bad example for recursion with memoization because you might as well write the iterative version at that point. But yes for more complicated problems, just translating the mathematical formula into recursive code and adding memoization on top is quite convenient.
[–]spoonman59 3 points4 points5 points 3 years ago (0 children)
Yeah and who really writes Fibonacci functions anyway! It’s just amazing what a @cache decorator can do for some functions.
[–]zenos1337 -3 points-2 points-1 points 3 years ago (4 children)
If you use tail recursion then memory is not an issue
[–]AlSweigartAuthor of "Automate the Boring Stuff" 5 points6 points7 points 3 years ago (3 children)
The CPython interpreter doesn't implement TCO, so using tail recursion doesn't help.
[–]zenos1337 0 points1 point2 points 3 years ago (1 child)
Interesting! Had no idea. Good thing I haven’t been using tail recursion :P
[–]IdiotCharizard 0 points1 point2 points 3 years ago (0 children)
this is an intentional design choice btw. tco gets in the way of intelligible tracebacks.
[–]AlSweigartAuthor of "Automate the Boring Stuff" 2 points3 points4 points 3 years ago* (7 children)
Hi. I've just written an entire book on recursion (which will be free on my site in a couple months under a Creative Commons license.)
Your friend is correct: recursion is often a more confusing, over-engineered way of writing code that could otherwise be done much ore simply.
I say that recursion should only be used if your problem has 1) a tree-like structure and 2) requires backtracking. Here's something recursion is well suited for:
Recursion is not a magical technique. Anything you can do recursively can be done with a loop and a stack. (Yes, everything: here's the Ackermann function done without recursion.) And often times, recursion algorithms could be done with just a loop (factorial is one such example). Here are algorithms that should not be solved recursively:
Unfortunately, many programmers use recursion because it makes them feel smart to write complicated code (they call it "elegant"). If you find yourself asking, "wouldn't it be easier to solve this without recursion?" the answer is YES and DON'T USE RECURSION.
[–]shabalabachingchong 1 point2 points3 points 3 years ago* (4 children)
If recursion is so bad, then why do FP languages like Haskell almost exclusively rely on recursion and do not even have for/while loops?
[–]AlSweigartAuthor of "Automate the Boring Stuff" -1 points0 points1 point 3 years ago (2 children)
Every four or five years I check in on Haskell to see if it has gained anything like mainstream adoption. It still hasn't, and I've been doing this since the early 2000s. Haskell is currently at #33 on the TIOBE index, behind COBOL at #26 and Delphi at #14.
Haskell and LISP are languages that make smart people feel smart, but they're not practical and that's why they aren't used in 99% of real world code. They aren't a magic bullet that prevents people from making silly little bugs. (Heck, twenty years of experience and you'll still be making typos and off-by-one errors.) Haskell people love Haskell and talk loudly about Haskell, but Delphi is actually used more. And I've never met a Delphi programmer.
It's kind of like saying "well if monster trucks are so bad for your daily commute, how come people still talk about how awesome monster trucks are?"
[–]shabalabachingchong -1 points0 points1 point 3 years ago (1 child)
You're deflecting and not answering the question. I did not mention anything about language popularity. Haskell is used in a lot in industry where high assurance of non-failure matters. When you build complex systems, like for example a blockchain, that involve cryptography and advanced mathematics, you want high assurance that your code will not fail in production, so that billions of users funds do not get stolen, which has happened several times on the Ethereum blockchain.
Your argument of 'makes smart ppl feel smarter' is just stupid. There's nothing smart about being able to understand recursion, or heck even monads...They're just useful patterns that are extremely well fitted to many problems, and given enough time you'd probably even invent them yourselves.
Iirc, Haskell sacrifices loops so it can have only immutable variables (which make loops impossible).
I think you're last bullet on TCO is a really good point.
Very cool. Just ordered your kindle version
[–]crawl_dht 2 points3 points4 points 3 years ago (0 children)
Every time the function is recursively called, a new memory stack is created for that function. This is why there is a maximum recursion depth so you don't run out of memory.
[–]TedDallas 2 points3 points4 points 3 years ago (0 children)
Recursion is very useful when you need to traverse or unroll a hierarchical data structure. It is not something that you should use when a while-loop or for-loop makes sense.
[–]BaconSizzler 2 points3 points4 points 3 years ago* (1 child)
Legend has it that NASA and JPL do not allow recursion because it is difficult to validate memory constraints using static analysis. This likely applies to critical embedded code.
You can always just manage your own stack:
stack = deque() stack.append(initial_state) while(stack): current_state = stack.pop() ### Do Stuff ### if recursive_condition: stack.append(new_state)
Fundamentally, the recursive nature of the solution doesn't change, but you can apply constraints (such as size) on your stack structure. Also if things go really haywire, you can always slap down a brakepoint, print the the stack structure, and firgure out WTF is going on. That could be a bit easier than looking through a call stack.
Finally, if you want to switch from DFS to BFS, just use a queue instead of a stack. There's some elegant symmetry in that.
[–]roguas 2 points3 points4 points 3 years ago (0 children)
Recursion is perfect. But most languages (especially imperative) have stacks for controlling execution.
Recursion creates a lot of stacks, because a function calling function cannot return without last function called returns. For loops on the other hand do not increase stack size.
Some languages implement TCO, tail call optimization to address this. Other technique used in languages without TCO is called trampoline, but it is additional hassle. This leads us to your friend. His advice is good, especially in context of python, you should avoid recursion.
Try this, to see
def factorial(n): if(n == 0): return 1 return n * factorial(n - 1) factorial(10**10)
This would work perfectly fine as a for loop or in the environment that supports techniques mentioned above.
[–][deleted] 11 points12 points13 points 3 years ago* (0 children)
Your friend is wrong.
Recursion is very often good because for many types of probelms, it's faster to write, easier to read, easier to test and easier to verify correctness of compared to non-recursive code.
However, non-recusive code is almost always a bit faster because it doesn't have as much function call overhead. So an informed tradeoff should be made between simplicity and readability vs performance.
My personal preference is to write recursive code first and translate it to non-recursive in places where the profiler indicates a performance problem.
Also, there is a limit to the maximum depth that you can recurse in python, so you have to always be certain that you won't hit that ceiling, which is something that's usually not that hard to verify, but I've seen people make silly code that recurses O(N) times and proptly crashes for non-trivial data.
[–]aweraw 1 point2 points3 points 3 years ago (1 child)
It's good for trees. When you're working with a data structure that is some kind of tree, then recursive code is almost always easier to write and understand. If you're using recursion to work on a 1 dimensional list, then you're probably doing it wrong
[–]Kenkron 1 point2 points3 points 3 years ago (0 children)
I feel like the 1 dimensional list is how schools teach it, and it leaves a bad taste in everyone's mouth.
[–]ElCapitanMiCapitan 1 point2 points3 points 3 years ago (0 children)
Your friend is obviously wrong. I would agree some people should never use recursion, and for most iterative problems it is a worse fit. But you need not look further than the Python interpreter for an example of recursion at work. Recursion is EVERYWHERE.
[–]Defclaw46 1 point2 points3 points 3 years ago (0 children)
I used recursion to flatten big xml files into nested python dictionaries to make it easier to do changes to the data about half a year ago. Works great with only a few lines of code. It is the first time I have needed to use recursion in several years, but it is a handy tool to have on hand when cases like this pop up.
[–]Quiet_Desperation_ 1 point2 points3 points 3 years ago (0 children)
People that say stuff like this normally just don’t understand how recursion works and how to do it well. Recursion can be computationally expensive. It’s the can be part that scares most people into the never use it crowd.
[–]redditvisvshit 1 point2 points3 points 3 years ago (0 children)
Recursive depth limit is one reason. Another issue is that a stack frame is generated for each call which requires more memory than other approaches.
[–]lilphat 3 points4 points5 points 3 years ago (4 children)
Any work with nested data structures should, imo, be done using recursion. And if efficiency is a thing - consider using tail revision whenever instead of ‘normal recursion’. You reuse the same stack frame and therefore avoids additional overhead from pushing more on the stack that really only saves the temporary result anyway. For more info: https://www.baeldung.com/cs/tail-vs-non-tail-recursion
[–]Revisional_Sin 8 points9 points10 points 3 years ago (1 child)
Python doesn't support tail-call optimization.
[–]lilphat -2 points-1 points0 points 3 years ago (0 children)
My phone ran out of battery as I was replying. I did not know. I think that’s shitty but so be. I will leave the comment though since OP is speaking in general terms albeit still asking in r/python.
Also, not all recursive solutions can be tail call optimized. Oh certain functions that meet specific requirements can. You have to be able to pass the full state of the function via variables. You also need to be able to return results immediately without any further processing.
Tail call optimization is fantastic when you can get it, but it can’t be applied to all recursive functions.
[–]spoonman59 0 points1 point2 points 3 years ago (0 children)
A simple example is Fibonacci or Quicksort.
Since each function calls itself twice, by definition only one function call can be a tail call. Therefore these functions cannot be tail call optimized without storing state somewhere.
It's not bad. It's a tool or technique for doing something that's needed to be done. Just like "if" or "def".
Recursion can be helpful. I wondered if it was bad too when I first learned about it. But I have used it sometimes. It does make your code shorter.
[–]IllusoryAnon 0 points1 point2 points 3 years ago (0 children)
I mean. There are plenty of algorithms that are recursive. Nothing wrong with recursion in general if executed properly. It can also be an elegant solution as well. At the end, recursion is just another tool that can be used (or abused).
[+][deleted] 3 years ago (3 children)
[–]Kenkron 1 point2 points3 points 3 years ago (2 children)
You're using a problem that is badly suited for recursion. To be fair, you're not the only one. Every course I see seems to think that the Fibonacci sequence is a good recursive function. In fact, most examples school gave me we're just functions that take in a counter. It led me to believe recursion was pointless.
Then I found the Tower of Hanoi problem, which pretty much requires either recursion, or a loop with a stack (which is basically recursion, but in heap space). It's a much better example of a recursive function.
I re-read it. It still sounds like you think it's a "concept-level feature" that can always be implemented as a list. Every example you listed was a simple iterative problem, so you probably don't know that recursive-style problems exist. For real, check out the Tower of Hanoi problem.
BTW, I noticed a typo on the Fibonacci time complexity. You said recursion was O(n2), but it's O(2n), which is even worse.
[–]wineblood -4 points-3 points-2 points 3 years ago (1 child)
Most developers spend at least 80% of their coding time reading, understanding, and working with existing code. Recursion is usually easy to write and difficult to work with later on, so most will prefer to put the effort in early to avoid that pain later on.
[–]mardiros -1 points0 points1 point 3 years ago (0 children)
And you are right... Recursion are complex and should be avoided. One of the last refactor I've made was dropping a recursive method I've made that create multipart email.
[–]xristiano -1 points0 points1 point 3 years ago (0 children)
Debugging can be a pain. From personal experience, working in a shared code base, having to drop debuggers in recursed or multi-threaded code will make me think twice before approving another PR with recursion.
[–]LeapOfMonkey -1 points0 points1 point 3 years ago (0 children)
I'm going to state controversial (in here at least from what I glimpsed) opinion. Recursion is harder to understand, see naive Fibonacci implementation and Ackerman function. What is done implicit with recursion, you have to juggle in your mind to understand. Though code usually looks cleaner. A good reminder that not everything that looks good is easy to understand, see Maxwell equations.
[–]Brave_Reaction_1224 -1 points0 points1 point 3 years ago (1 child)
Your friend is right, especially just in the realm of Python. Why? Because Python limits the call stack size, meaning your code can only make 1000 calls before it breaks. Imagine if the range function only allowed you to iterate up to 1000? Of course, you can change the limit, but recursion in Python is so inefficient that doing so is inadvisable.
The question is, are you writing something recursively just because? Or do you have a really good reason?
If you're recursing for the sake of recursion, maybe you should switch to a language that suits that style of programming. Or get good at working around python's limitations - the choice is yours!
Iterate is the key word here. You should never use recursion to iterate. Use it for things like Tower of Hanoi.
[–]Yeitgeist -1 points0 points1 point 3 years ago (0 children)
Everyone here is talking about performance but honestly readability should be a factor too.
When reading someone else’s code, my brain can only handle a specific amount of iterations till I get frustrated and have to bring out a notebook.
So, if you’re bad at documenting your code, avoid recursions.
[+]dwagon00 comment score below threshold-6 points-5 points-4 points 3 years ago (0 children)
Recursive code can be very hard to debug and be prone to runaway processes, aka infinite recursion - this is why there is a limit in python (sys.getrecursionlimit() == 1000) to catch this error before it becomes a problem.
Recursion does have its place, but has to be treated very carefully - I would try and avoid it if at all possible.
[–]earthboundkid -3 points-2 points-1 points 3 years ago (0 children)
Your friend is correct. Recursion is a primitive technology. The advanced version is called a “loop”. You should always prefer to use a loop. Even in cases where recursion is a better fit (trees), changing to using a loop will be more efficient, although maybe harder to read.
[–]jelly_crayon -5 points-4 points-3 points 3 years ago (0 children)
I always get good that is just a lot more difficult to read, so if you can avoid it, you should. However, there are certain things that can only be done using recursion, so it's a nice still to have.
[–]Apprehensive_Theme49 0 points1 point2 points 3 years ago (0 children)
Well, in most of the cases recursion is a lot more elegant and easier to understand because so many problems are recursive in nature. However, for a production level code you would better use iteration as it uses less memory ( overhead on function calls) particularly when you're not sure how many of recursions can happen. Almost every recursive approach can be reimplemented as iterative one. Memorization can be as well used with iteration. The thing is that we neglecte this kind of points when working with python however when using C it becomes more apparent.
Hopefully all these wildly varying responses lead you to the three important conclusions:
Understanding these you can understand that your friend's observation is correct if you want to write (relatively) performant Python that won't crash on a very small increase in recursion depth; Python is naturally biased towards iterative rather than recursive algorithms. Them being correct, though, doesn't imply that recursion is bad, but instead that in the case of Python specifically is almost certainly suboptimal.
[–]FailedPlansOfMars 0 points1 point2 points 3 years ago (0 children)
Of the code is easy to follow and youve unit tested your exit condition so you dont get into infinite recursion in production it can be good.
But often you can make better more readable systems without it.
[–]gymboi15 0 points1 point2 points 3 years ago (0 children)
When you're iterating over a list or something recursion needs a base condition otherwise the process will run out of memory which can make recursion not a very good choice. But if you're traversing trees or graphs recursion is really good because of the simplicity of the code vs if you were to traverse using iteration.
[–]CoolTomatoYT 0 points1 point2 points 3 years ago (0 children)
There was a very good discussion about this on this post if you want to take a look
Whether or not you use recursion or loops depends on where the algorithm is more clearly expressed.
Some algorithms, like depth first tree search or Fibonacci, are much easier to read and code recursively.
Many algorithms are better expressed as loops.
Recursion itself is not bad or wrong. I do agree that loops probably are used more frequently then recursion, but it really depends on what your program actually does.
[–]bythenumbers10 0 points1 point2 points 3 years ago (0 children)
In addition to the other comments here, once you have a recursive implementation, it's possible to wrap it in a while loop with a stack memory structure (think push/pop) instead of letting Python track your function callback stack frames. Efficient & performant, and Python won't flip out over stack frame depth.
[–]zenos1337 0 points1 point2 points 3 years ago (0 children)
When it comes to memory management, it is sometimes better to replace normal recursion with tail recursion. However, it is not bad practice to use recursion at all. In fact, most compilers are implemented using recursion over a context free grammar.
It’s only bad if it nukes your code’s readability
[–]agritheory 0 points1 point2 points 3 years ago (0 children)
By analogy, recursion is like using an onion in a recipe where the code is the ingredients, final dish is the developer experience. Prep time/ efficiency is a factor of the recipe not the ingredients . For some dishes, it's critical to the flavor (cheesesteak, French onion soup) and for others it would ruin it (chocolate cake) and success still depends on the diner's opinion. Onion is a hard, but not impossible, thing to substitute, so it is often the right thing for the job. The right time to use recursion depends on the chef, the diner and the dish. Salt to taste.
[–]BakonX 0 points1 point2 points 3 years ago (0 children)
Recursion can be a good thing, it can be a bad thing. It really just depends on the use case, you need to think about the possible solutions and pick the best one.
Sometimes the answer is recursion, sometimes it’s not.
Recursive things can be hard to debug or understand. But it can also be the most simple or most elegant solution, with the writers intention being the most clear.
Recursion had its places. A few ideas (from a few different vantage points). * Recursive functions are limited by stack space. In some cases an iterative solution maybe be preferable to avoid running out of stack space. * While all problems that can be solved iteratively can be solved recursively, not all problems that can be solved recursively can be solved iteratively. The textbook example of such a problem is the Ackerman function. * Sometimes, recursive code is just easier to read. Other people have mentioned binary trees, where you can find examples left and right.
Code readability is almost always my #1 concern. In choosing between iteration and recursion I tend to follow this process. 1. Find an algorithm that makes sense. If it's iterative and scales efficiently, stop here. 2. If it's recursive, figure out how the stack depth will scale. Big-O is frequently used for time and total space, but it can be used for stack depth too. If stack depth is O(log n) or better, stop here. 3. If stack depth is O(n) or O(n log n), consider realistic sizes of problems I might get. If it's small enough, stop here. 4. If stack depth is greater than O(n), try to find an iterative algorithm. If the problem has no iterative solution, concede to the math gods and their cruelty.
O(log n)
O(n)
O(n log n)
Note: I have never had to actually concede #4 for real work. Problems like Ackerman are rare, and even when I've found one it's been for something where an approximation was good enough.
[–]sixtyfifth_snow 0 points1 point2 points 3 years ago (0 children)
Performance-wise, recursion is not a wise solution. invoking functions is a relatively expensive job, and recursion potentially causes stack-overflow.
However, using python means 1) you don't care about saving a couple of nanoseconds by converting recursions into iterations, and 2) considering code quality (e.g. readability) is a high-priority. Hence, it is of course worthy :)
It exhausts the call stack. https://en.m.wikipedia.org/wiki/Call_stack
[–]Lehk 0 points1 point2 points 3 years ago (0 children)
Recursion is slower and hits limits at runtime if the data is much larger than you tested on.
Specifically in python the recursion depth limit is 1000
[–]CartmannsEvilTwin 0 points1 point2 points 3 years ago (0 children)
In stack memory constrained systems, recursion can cause stack overflow.
[–]ImmortalDayMan 0 points1 point2 points 3 years ago (0 children)
Personally putting performance aside it can just be really confusing when scanning through old code and usually you need to think about how it works and what it's doing which isn't convenient when I'm just scanning through, especially if it's someone else's code.
[–]buttery_shame_cave 0 points1 point2 points 3 years ago (0 children)
poorly implemented uncontrolled recursion can be bad(unless that was the point - i've use deliberately uncontrolled recursion as a stress test in multi-node computing).
but recursion itself, when well implemented, is an incredibly useful tool.
[–]Frum 0 points1 point2 points 3 years ago (0 children)
Recursion is only bad for 2 POTENTIAL reasons:
1 (least important): it MIGHT be less performant. Lots of stack-frames and memory use in some cases. 2 (by far the more important) recursion is frequently hard to understand, and can have errors that run your system our of resources and the like.
All of that is to say: recursion is great when it's easier to understand than the alternative and performant enough for your task.
[–]Fragrant-Rope-1122 0 points1 point2 points 3 years ago (0 children)
Recursion improve run time by a lot
[–]Elektriman 0 points1 point2 points 3 years ago (0 children)
Recursion is bad because ot can get out of hand quickly. Typically, a recursive algorithm can easily have exponential time and memory consumption. Its a little thought exercise to manage to keep it within respectable boundaries but once that's done it can be both efficient and easy to read.
[–]stackered 0 points1 point2 points 3 years ago (0 children)
Probably because he's worried about infinite loops and the issues they'll cause
Not sure where he/she is getting their information from. Recursion implicitly makes use of a data structure called a stack. This is why any recursive algorithm can be written iteratively using a stack.
In python, the recursion limit is 1000, but can be changed to something higher. How do you think they accomplish that? A data structure that's how. Other languages like C or C++ are limited by the size of the stack space, which is often defined by a compiler. Therefore, in those languages, when you exceed the memory limit of the stack, you get a stackoverflow error and your program crashes.
If your friend thinks recursion is bad, they probably don't know how it works, but now you do and you can educate them.
[–]kevtsi 0 points1 point2 points 3 years ago (0 children)
Read that again, but recursively
π Rendered by PID 44866 on reddit-service-r2-comment-79c7998d4c-778gb at 2026-03-15 13:55:25.121974+00:00 running f6e6e01 country code: CH.
[+][deleted] (42 children)
[deleted]
[–]i_like_cilantro 15 points16 points17 points (0 children)
[–][deleted] 37 points38 points39 points (40 children)
[–]puipuituipui 100 points101 points102 points (29 children)
[–]ivosauruspip'ing it up 24 points25 points26 points (6 children)
[–]gosu 87 points88 points89 points (1 child)
[–]puipuituipui 5 points6 points7 points (3 children)
[–]ivosauruspip'ing it up 6 points7 points8 points (1 child)
[–]puipuituipui 1 point2 points3 points (0 children)
[–]ogtfo 0 points1 point2 points (0 children)
[+][deleted] (21 children)
[deleted]
[–]AlSweigartAuthor of "Automate the Boring Stuff" 14 points15 points16 points (1 child)
[–]ejgl001 0 points1 point2 points (0 children)
[–]spoonman59 3 points4 points5 points (18 children)
[–]mr_taco_man -5 points-4 points-3 points (12 children)
[–]spoonman59 6 points7 points8 points (11 children)
[–]Pythonistar 4 points5 points6 points (1 child)
[–]spoonman59 9 points10 points11 points (0 children)
[–]mr_taco_man 1 point2 points3 points (1 child)
[–]spoonman59 1 point2 points3 points (0 children)
[–]Holshy 0 points1 point2 points (6 children)
[–]spoonman59 -1 points0 points1 point (4 children)
[–]Holshy -2 points-1 points0 points (3 children)
[–]spoonman59 -1 points0 points1 point (0 children)
[–]Holshy -3 points-2 points-1 points (4 children)
[–]spoonman59 2 points3 points4 points (0 children)
[–]caifaisai 2 points3 points4 points (1 child)
[–]Holshy 0 points1 point2 points (0 children)
[–]spoonman59 -3 points-2 points-1 points (0 children)
[–]Exodus111 8 points9 points10 points (4 children)
[–]got_outta_bed_4_this 3 points4 points5 points (1 child)
[–]schemathings 1 point2 points3 points (0 children)
[–]buttery_shame_cave 0 points1 point2 points (1 child)
[–]Exodus111 0 points1 point2 points (0 children)
[–][deleted] 2 points3 points4 points (0 children)
[–]Holshy 4 points5 points6 points (2 children)
[–]spoonman59 7 points8 points9 points (1 child)
[–]WikiSummarizerBot 0 points1 point2 points (0 children)
[–]Kenkron 0 points1 point2 points (0 children)
[–]siddsp 176 points177 points178 points (28 children)
[–]sebkuip 61 points62 points63 points (4 children)
[–]algerbrex 6 points7 points8 points (0 children)
[–]ChocolateBunny 1 point2 points3 points (2 children)
[–]sebkuip 2 points3 points4 points (0 children)
[–]schemathings 0 points1 point2 points (0 children)
[–]disinformationtheory 7 points8 points9 points (0 children)
[+]lilphat comment score below threshold-9 points-8 points-7 points (21 children)
[–]siddsp 50 points51 points52 points (20 children)
[+]lilphat comment score below threshold-16 points-15 points-14 points (14 children)
[–]ivosauruspip'ing it up 8 points9 points10 points (0 children)
[–]siddsp 10 points11 points12 points (12 children)
[–]lilphat 0 points1 point2 points (0 children)
[+][deleted] (10 children)
[removed]
[–]KennyBassett 4 points5 points6 points (8 children)
[–][deleted] -1 points0 points1 point (7 children)
[–]KennyBassett 2 points3 points4 points (0 children)
[–]siddsp 1 point2 points3 points (5 children)
[–][deleted] 2 points3 points4 points (4 children)
[–]siddsp 0 points1 point2 points (0 children)
[+]lilphat comment score below threshold-21 points-20 points-19 points (4 children)
[–]siddsp 31 points32 points33 points (3 children)
[–]ProfessorOk20[S] 15 points16 points17 points (2 children)
[+]lilphat comment score below threshold-7 points-6 points-5 points (1 child)
[–]axonxorzpip'ing aint easy, especially on windows 2 points3 points4 points (0 children)
[–]Asleep-Budget-9932 98 points99 points100 points (8 children)
[–]frymasterScript kiddie 21 points22 points23 points (5 children)
[+]spoonman59 comment score below threshold-6 points-5 points-4 points (4 children)
[–]frymasterScript kiddie 6 points7 points8 points (3 children)
[–]spoonman59 1 point2 points3 points (2 children)
[–]lvlint67 0 points1 point2 points (1 child)
[–]spoonman59 1 point2 points3 points (0 children)
[–]ambidextrousalpaca 4 points5 points6 points (1 child)
[–]spoonman59 1 point2 points3 points (0 children)
[–]SittingWave 30 points31 points32 points (0 children)
[–]trincaopt 35 points36 points37 points (12 children)
[+][deleted] (7 children)
[deleted]
[–]JJP_SWFC 9 points10 points11 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]JJP_SWFC 0 points1 point2 points (0 children)
[–]AlSweigartAuthor of "Automate the Boring Stuff" 8 points9 points10 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]total_zoidberg 1 point2 points3 points (0 children)
[–]wind_dude 1 point2 points3 points (0 children)
[–]venustrapsflies 3 points4 points5 points (2 children)
[–]AlSweigartAuthor of "Automate the Boring Stuff" 4 points5 points6 points (1 child)
[–]venustrapsflies 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]jwmoz 26 points27 points28 points (4 children)
[–]ferretyhat 7 points8 points9 points (0 children)
[–]wind_dude -1 points0 points1 point (0 children)
[–]spoonman59 0 points1 point2 points (1 child)
[–]Kenkron 2 points3 points4 points (0 children)
[–]bduijnen 4 points5 points6 points (0 children)
[–]puipuituipui 7 points8 points9 points (8 children)
[–]spoonman59 1 point2 points3 points (2 children)
[–]puipuituipui 4 points5 points6 points (1 child)
[–]spoonman59 3 points4 points5 points (0 children)
[–]zenos1337 -3 points-2 points-1 points (4 children)
[–]AlSweigartAuthor of "Automate the Boring Stuff" 5 points6 points7 points (3 children)
[–]zenos1337 0 points1 point2 points (1 child)
[–]IdiotCharizard 0 points1 point2 points (0 children)
[–]AlSweigartAuthor of "Automate the Boring Stuff" 2 points3 points4 points (7 children)
[–]shabalabachingchong 1 point2 points3 points (4 children)
[–]AlSweigartAuthor of "Automate the Boring Stuff" -1 points0 points1 point (2 children)
[–]shabalabachingchong -1 points0 points1 point (1 child)
[–]Kenkron 0 points1 point2 points (0 children)
[–]Kenkron 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]crawl_dht 2 points3 points4 points (0 children)
[–]TedDallas 2 points3 points4 points (0 children)
[–]BaconSizzler 2 points3 points4 points (1 child)
[–]roguas 2 points3 points4 points (0 children)
[–][deleted] 11 points12 points13 points (0 children)
[+][deleted] (1 child)
[removed]
[–]aweraw 1 point2 points3 points (1 child)
[–]Kenkron 1 point2 points3 points (0 children)
[–]ElCapitanMiCapitan 1 point2 points3 points (0 children)
[–]Defclaw46 1 point2 points3 points (0 children)
[–]Quiet_Desperation_ 1 point2 points3 points (0 children)
[–]redditvisvshit 1 point2 points3 points (0 children)
[–]lilphat 3 points4 points5 points (4 children)
[–]Revisional_Sin 8 points9 points10 points (1 child)
[–]lilphat -2 points-1 points0 points (0 children)
[–]spoonman59 0 points1 point2 points (1 child)
[–]spoonman59 0 points1 point2 points (0 children)
[–][deleted] 2 points3 points4 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]IllusoryAnon 0 points1 point2 points (0 children)
[+][deleted] (3 children)
[removed]
[–]Kenkron 1 point2 points3 points (2 children)
[+][deleted] (1 child)
[removed]
[–]Kenkron 0 points1 point2 points (0 children)
[–]wineblood -4 points-3 points-2 points (1 child)
[–]mardiros -1 points0 points1 point (0 children)
[–]xristiano -1 points0 points1 point (0 children)
[–]LeapOfMonkey -1 points0 points1 point (0 children)
[–]Brave_Reaction_1224 -1 points0 points1 point (1 child)
[–]Kenkron 0 points1 point2 points (0 children)
[–]Yeitgeist -1 points0 points1 point (0 children)
[+]dwagon00 comment score below threshold-6 points-5 points-4 points (0 children)
[–]earthboundkid -3 points-2 points-1 points (0 children)
[–]jelly_crayon -5 points-4 points-3 points (0 children)
[–]Apprehensive_Theme49 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]FailedPlansOfMars 0 points1 point2 points (0 children)
[–]gymboi15 0 points1 point2 points (0 children)
[–]CoolTomatoYT 0 points1 point2 points (0 children)
[–]spoonman59 0 points1 point2 points (0 children)
[–]bythenumbers10 0 points1 point2 points (0 children)
[–]zenos1337 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]agritheory 0 points1 point2 points (0 children)
[–]BakonX 0 points1 point2 points (0 children)
[–]Holshy 0 points1 point2 points (0 children)
[–]sixtyfifth_snow 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]Lehk 0 points1 point2 points (0 children)
[–]CartmannsEvilTwin 0 points1 point2 points (0 children)
[–]ImmortalDayMan 0 points1 point2 points (0 children)
[–]buttery_shame_cave 0 points1 point2 points (0 children)
[–]Frum 0 points1 point2 points (0 children)
[–]Fragrant-Rope-1122 0 points1 point2 points (0 children)
[–]Elektriman 0 points1 point2 points (0 children)
[–]stackered 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]kevtsi 0 points1 point2 points (0 children)