A function might want to call itself if it encounters a subproblem that has the same shape as the overall problem. It’s important that the subproblem is smaller, or otherwise this would be a never-ending cycle.
After removing the first element, you would indeed have a problem of the same shape that is smaller. But if the function solves “the rest” by calling itself, then why would it continue looping after that? It should be one or the other.
Without the loop, that would be … not a great solution, but one that makes sense. It’s still not great because it is still removing from the front, and just like with the list-on-paper-starting-on-the-left-edge, that isn’t a cheap operation.
Like mentioned though, you could remove from the back instead, that doesn’t cause the start of the list to move, this is a cheap operation.
You’d still run into yet another problem, which is that python will only keep track of about 1000 calls in progress (can be increased, but not to large amounts like 100k, much less hundreds of millions)
Stick to incredibly basic operations. Fancy things are built from smaller things, you can build yourself up from what you understand to more powerful operations (and then you understand those too). If you for example need to reverse something, then you could do that by copying the whole list to get another list of the same size (or insert zeros or whatever, only the size matters since you’ll overwrite all of it), then iterating again but this time copying to the opposite end. Or, iterate backwards through the original list, and add each value to an initially empty list. After that you will have implemented reversing, and if you implemented it in a separate function then you’ve got a reusable function for reversing.
Then, when you understand how to write something you might start looking for shorter code doing the same thing, but that comes after understanding.
You said somewhere that the concepts make sense but that you didn’t know how to turn them into code. Well, I think you understand them at the wrong abstraction level. Break them down further until they are small enough problems that you know how to solve, and then join the solutions of those small problems together into increasingly more powerful solutions.
Getting the sum of digits might seem like something difficult to implement, but there are two obvious subproblems in that. Sum, and digits. Solve them separately, then combine
digits may also be opaque, but again, it breaks down. What is the number at the lowest digit? Get that, divide the rest by 10, do it again. Repeat (combine) to get all digits. Or, what is the ascii value of ‘9’? What values do ‘0’ ‘1’ … etc have, is there a pattern, can the integer digits be obtained from those values? Isn’t that what you do manually to compute digit sum? Look at each character and add up its corresponding value.
How you manually solve a problem is usually a good reference, or another way to put is that you should understand how to solve the problem before writing the code for the solution, otherwise you can’t possibly be writing code that solves the problem.