confusion about a python recursion function - python

I got a print_backward function code online, but I am so confusing
about how it works and its output.
The below is my code.
def print_backward(num):
if num == 10:
return
num += 1
print(num)
print_backward(num)
print("yeah")
print(num)
print()
print_backward(6)
The below is output.
7
8
9
10
yeah
10
yeah
9
yeah
8
yeah
7
I can understand how it prints from 7 to 10, since each time it call
recursively, num += 1.
But I am confusing, once num achieves 10, the print_backward should
return, then done. It should not print yeah 10, yeah 9, yeah 8, yeah
7. Why this code has called return, how it still can print? How this code works to print backward, which means why I called print(num), it
can print from 10 to 7?

Function call is actually a stack operation. And recursion is a special case of function call.
Every time you call a function, the Return Address will be push into a stack, and when the function return, the program will pop the Return address from the top of stack, and program continue to execute from there. You can have a look at the official description about call stack in wikipedia.
For your example, print_backward(7) call first, and then the next command will push into the stack, and then when you call the print_backward(8), the next command will be pushed into the stack again, so after 4 recursion call, the stack will be like this:
+-------------------------+ <--- Stack top
| num = 10, print("yeah") | \
| num = 9, print("yeah") | |
| num = 8, print("yeah") | > Call stack
| num = 7, print("yeah") | |
+-------------------------+ /
The criteria hit the if condition num == 10: when calling from print_backward(10). The program execute return statement, the Return address from the stack top will be pop, and program starts from there, that means, print('yeah') for num = 10 will be execute. After finished call for print_backward(10), the stack will pop another Return Address from the stack, and print('yeah') in print_backward(9) will be executed. This operation will be ended when the stack is empty, that means ,there is no more function return.

On the first runs, the code does not go further than the inner call to print_backward(num), that is 4 times (like an infinite recursion)
When the argument reaches 10, all the functions return and it goes further, printing the original num+1 with which they were called.
The highest numbers are printed first because the calls where the number is higher return first.

The function calling happens through stack.
You call print_backward on 6. So stack will have 6.
Now you call it on 7 ---> So stack has 6,7 where 7 is top.
Now you call it on 8 ----> So stack is 6,7,8
Now on 9, So stack is 6,7,8,9
Now on 10, So stack is 6,7,8,9,10.
Now when function returns , it pops from stack.
So, you were in function with parameter 10. So, you called return and it gets popped from stack. Now stack is 6,7,8,9.
Now it prints "yeah" and 10 (because num is 9 and we did num = num + 1 before).
Now it returns and pops 9. Now stack is 6,7,8
Now it prints yeah and 9 because num is 8 and we did num = num +1 before).
Similarly, it prints other as well.

For your case - print_backward(6) it took 4 calls (recursively) to hit return criteria i.e. if num == 10 - during those calls the function printed:
7 # print_backward(6) - first call we made
8 # print_backward(7) - recursive
9 # print_backward(8) - recursive
10 # print_backward(9) - recursive - inner most, where the return is executed
For next recursive call print_backward(10) the return condition gets true, and the function starts returning (starting from the inner most call) - as result the lines below the recursive call (line 6) get called i.e.
yeah # 4th call (inner most) returned
10
yeah # 3rd call returned
9
yeah # 2nd call returned
8
yeah # 1st call returned
7
The call stack view visualization 'd be:
print_backward(6)
| 7 # num += 1 and then print(num)
| print_backward(7)
| | 8
| | print_backward(8)
| | | 9
| | | print_backward(9)
| | | | 10
| | | | | print_backward(10)
| | | | | | return
| | | | yeah # print("yeah")
| | | | 10 # print(num)
| | | | () # print()
| | | yeah
| | | 9
| | | ()
| | yeah
| | 8
| | ()
| yeah
| 7
| ()

when print_backward(6) is called then
1 check for 10
2 increase 6 by one num = 7
3 print 7
4 call backward with 7
for 6 print_backward is not completed yet and print_backward(7) is pushed on the top of stack. The remaining part
print("yeah")
print(7)
will execute at last when the recursive call is completed. I am skipping check 10 in the below steps. Will include that in last steps.
5 increase 7 by one num = 8
6 print 8
7 call backward with 8 (7 not completed)
8 increase 8 by one num = 9
9 print 9
10 call backward with 9 (8 not completed)
11 increase 9 by one num = 10
12 print 10
return is encountered
13 call backward with 10 (9 not completed)
14 check for 10 and return. 9 will continue for the execution.
15 in the execution of 9 num is 10 so yeah is printed and then 10 is printed and print_backward for 9 is completed. Similarly for 8 num is 9 which print yeah followed by 9 and so on.

Related

why last output also varies in this block of python code?

I can understand first output of first example, that is 2 as the i += 1 makes value to 2 than print calls, I also understand the second example's first output that is 1 because print calls i then increment begins. But, what about the end, as we have already defined "while i < 6:" then why first example returns last output as 6 (why don't it breaks to 5)
I'm a beginner so treat me like a kid and write the answer that is easy to understand. Thank you! :)
i = 1
while i < 6:
i += 1
print(i) # Print output after i increment, see the result
>> The output is -
2
3
4
5
6
i = 1
while i < 6:
print(i) # Print output before i increment, see the result
i += 1
>> The output is -
1
2
3
4
5
I was expecting the output should be limited to 5 but it returns to 6 (in first example)
The while condition is only checked before each iteration, not after every statement inside the loop body. So on the last iteration, i == 5 and the condition i < 6 succeeds. It goes into the loop body, increments i to 6, and then prints that value.
i = 1
while i < 6:# initially i value is 1.
i += 1 # here you are incrementing. i value becomes 2.
print(i) # print starts from 2
in the last check i value becomes 5 then it increments to 6 and prints.
so the output starts from 2 and goes till 6.
>> The output is -
2
3
4
5
6
i = 1
while i < 6:
print(i) # Print output before i increment, see the result
i += 1
here you print the i value first and increment later .
you print the i value first
initially 1
then you print it . then you are incrementing it.
in the final check 5<6. it prints 5 and in the next increment as i value equals to 6. the while statement becomes false.
>> The output is -
1
2
3
4
5

Python incremental iterating loop [duplicate]

This question already has answers here:
Scope of python variable in for loop
(10 answers)
Closed 2 years ago.
This is my code
for i in range(0,5):
intl = i
print(intl)
intn = i+1
print(intn)
i+=1
print("---------")
What I am getting as the output is the following.
0
1
---------
1
2
---------
2
3
---------
3
4
---------
4
5
---------
Instead of that, I need to get;
0
1
---------
2
3
---------
4
5
---------
Sorry I made a mistake. What you are looking for is the step parameter of range() like this:
for i in range(0,5,2):
intl = i
print(intl)
intn = i+1
print(intn)
print("---------")
Now, for every loop it will skip one number (so i=0, then i=2, then i=4). When modifiying the variable i within a for loop, you will change the local version of i that is active in the current loop. Python doesn't actually use i to get the next item from a itterable, and thus manually changing it doesn't do anything for your loop.
You can simply do this:
for i in range(0, 5, 2):
intl = i
intn = i+1
print(intl)
print(intn)
print("---------")
Now the range function has a step of 2. The step is the difference between each number. By default, it's 1.
for i in range(0, 5):
print(i)
Returns:
0
1
2
3
4
for i in range(0, 5, 2):
print(i)
Returns:
0
2
4
In your code, you did this:
i+=1
This doesn't work because the variable i is set by the for loop in each iteration. This means that no matter what you do with the i variable, in the next iteration it will be 1 more than last time.
This code prints '-------' whenever the next value of i is divisible by 2.
x = 5
for i in range(0, x+1):
print(i)
if (i+1) % 2 == 0:
print('---------')

How does count work when passing an empty string? [duplicate]

This question already has answers here:
Why are str.count('') and len(str) giving different output?
(3 answers)
Closed 2 years ago.
I have a question, if I have
h = "hello world"
print (h.count(''))
That prints 12.
But if i do
print (h[11])
I get an IndexError: string index out of range
I don't understand the reason.
What does the count function count when passing an empty string?
The reason it prints 12 is that there are empty strings in between every letter, and at both sides. Here is a diagram:
All empty strings!
^h^e^l^l^o^ ^w^o^r^l^d^
it looks weird, but every ^ is an empty sn empty string, and if you count them, there are 12.
The reason you are getting the error is that a string is just an array of characters, so it is zero-indexed, meaning that the first element is index 0, the second at index 1, and so on. Here is a diagram:
-------------------------------------
a | b | c | d | e | f | g | h | i | j
-------------------------------------
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
-------------------------------------
As you can see, the tenth element (j), is at index 9, so trying to get index 10 would result in an error.
The String Hello World Can only be indexed up to 10. Remember that indexes start at zero
H the first character is 0
and d at the end is 10
when you do count(''), it includes a blank space after and before the String, so it adds two extra increments.
So you can do len(h)-1 or (h.count('')-2) to show the last element of the strings index.
Note len() shows how many elements are in a list not the index of the last one. The last element of a string or list is len()-1

Appending To Files Challenge

I write a program to append the times table for our poem in sample.txt
So , this is all of my code
numbers = 1
for i in range(2, 12):
while 13 >= numbers > 0:
multiply = numbers * i
print('| {0} Times {1} is {2} '.format(numbers, i, multiply))
numbers += 1
print('=' * 21)
with open('times_table.txt', 'w') as times:
for table in times:
print(table, file=times)
and the output is:
| 1 Times 2 is 2
| 2 Times 2 is 4
| 3 Times 2 is 6
| 4 Times 2 is 8
| 5 Times 2 is 10
| 6 Times 2 is 12
| 7 Times 2 is 14
| 8 Times 2 is 16
| 9 Times 2 is 18
| 10 Times 2 is 20
| 11 Times 2 is 22
| 12 Times 2 is 24
| 13 Times 2 is 26
========================================
But because of code at the end lines for files appending , I'm facing this error below :
for table in times:
io.UnsupportedOperation: not readable
So , finally I don't know how to append this time table stuffs into a sample.txt file .
I really appreciate you all guys . If you can possibly help me with this .
If you want to append to the file, you should use 'a' instead of 'w' ! you can write these contents on file directly.
numbers = 1
with open('times_table.txt', 'a') as file:
for i in range(2, 12):
while 13 >= numbers > 0:
multiply = numbers * i
file.write(f'| {numbers} Times {i} is {multiply}\n')
numbers += 1
file.write('=' * 21)

Printing a string with start, stop, and step [duplicate]

This question already has answers here:
Understanding slicing
(38 answers)
Closed 7 years ago.
hello = "Hello there"
print(hello[10:0:-1])
This outputs:
ereht olle
And I can't figure out how or why.
print(hello[10:0:-2])
And this one outputs:
eetol
Could someone please help me to understand what the [10:0:-1] is actually doing?
Thanks!
The notation is in order start, stop and step. So you start at index ten, go to index zero where the endpoint is exclusive with a step of negative two, meaning backwards two. Here is a diagram of indices:
# -------------------------------------------------------------------
# | H | e | l | l | o | | t | h | e | r | e |
# -------------------------------------------------------------------
# X 5 4 3 2 1

Categories