# Why does this statement after a recursive call gets executed?

I have to write a code to simulate a one-on-one dual between 2 warriors. To do this I have written a class `Warriors` with `health` and `attack` as its attributes.

The duel occurs according to the following principle:

Every turn one of the warriors will hit another one, who will lose his health in the same value as the attack of the first warrior. After that, the second warrior will do the same to the first one.

To achieve the above logic, I have written the below recursive function called `lets_dual`.

``````class Warrior:
def __init__(self, x, y):
self.health = x
self.attack = y
self.is_alive = True

def lets_dual(warrior1, warrior2):

print('warrior1 health', warrior1.health)
print('warrior2 health', warrior2.health)

if warrior2.health > 1 and warrior1.health > 1:
# print('after attack warrior1 health', warrior1.health)
warrior2.health -= warrior1.attack
print('after attack warrior2 health', warrior2.health)

# check if warrior 2 is still alive or not
if warrior2.health > 0:
warrior1.health -= warrior2.attack
print('after attack warrior1 health', warrior1.health)

lets_dual(warrior1, warrior2)

print('this wont get printed')
elif warrior1.health > 0:
warrior2.is_alive = False
else:
warrior1.is_alive = False

dave = Warrior(50, 5)
carl = Warrior(50, 7)
print(lets_dual(dave, carl))
print(dave.is_alive)
``````

The problem is that the recursion logic is not working properly. Somehow the statement `'this wont get printed'` is getting executed. Also I want to add a return statement showing the `warrior2.is_alive flag` but it is returning `None` value.

On Best Solutions

I am not sure why do you even need recursion in the first place, you can easy replace your `if warrior2.health > 1 and warrior1.health > 1:` with a while loop which checks for the same thing `while warrior2.health > 1 and warrior1.health > 1:`

Running your logic over and over in a while loop is a lot better than looping using a recursion via an if condition.

Also note that you don't need to return anything from the `lets_dual` function, since you are worried about `warrior.health` which you can access after running the function, and `lets_dual` function just sets up the `is_alive` attribute for you!

So When I switch to a while loop

``````class Warrior:
def __init__(self, x, y):
self.health = x
self.attack = y
self.is_alive = True

def lets_dual(warrior1, warrior2):

print('warrior1 health', warrior1.health)
print('warrior2 health', warrior2.health)

#Replace if with a while
while warrior2.health > 1 and warrior1.health > 1:
# print('after attack warrior1 health', warrior1.health)
warrior2.health -= warrior1.attack
print('after attack warrior2 health', warrior2.health)

# check if warrior 2 is still alive or not
if warrior2.health > 0:
warrior1.health -= warrior2.attack
print('after attack warrior1 health', warrior1.health)

if warrior1.health > 0:
warrior2.is_alive = False
else:
warrior1.is_alive = False

dave = Warrior(50, 5)
carl = Warrior(50, 7)
lets_dual(dave, carl)
print(dave.is_alive)
print(carl.is_alive)
``````

The output comes out as

``````warrior1 health 50
warrior2 health 50
after attack warrior2 health 45
after attack warrior1 health 43
after attack warrior2 health 40
after attack warrior1 health 36
after attack warrior2 health 35
after attack warrior1 health 29
after attack warrior2 health 30
after attack warrior1 health 22
after attack warrior2 health 25
after attack warrior1 health 15
after attack warrior2 health 20
after attack warrior1 health 8
after attack warrior2 health 15
after attack warrior1 health 1
True
False
``````
On

What you need is a proper termination condition

``````class Warrior:
def __init__(self, x, y):
self.health = x
self.attack = y
self.is_alive = True

def lets_dual(warrior1, warrior2):

print('warrior1 health', warrior1.health)
print('warrior2 health', warrior2.health)

# Termination condition
if warrior2.health < 1:
warrior2.is_alive = False
print ("warrior2 is dead. Let's return")
return

# Termination condition
if warrior1.health < 1:
warrior1.is_alive = False
print ("warrior1 is dead. Let's return")
return

# Else let's battle
warrior2.health -= warrior1.attack
print('after attack warrior2 health', warrior2.health)

# check if warrior 2 is still alive or not
if warrior2.health > 0:
warrior1.health -= warrior2.attack
print('after attack warrior1 health', warrior1.health)

lets_dual(warrior1, warrior2)

dave = Warrior(50, 5)
carl = Warrior(50, 7)
print(lets_dual(dave, carl)) # This will print None as we return None from lets_dual
print(dave.is_alive)
``````
On

Like any function call, a recursive call returns control to the calling function after it's done. Compare it to calling `print`, the code keeps going after `print` gets done printing the text to the screen.

So if you have more code after your recursion, it will get run eventually, once the call is finished. If the extra code printed anything about the call, you might see the "unwinding" of the call stack, with the last caller running the code first, then it's caller doing so, and then its caller, and so on. Consider this function, which will print numbers in a range from 0 to the argument you pass in, using this unwinding to get them in the right order:

``````def print_range(n):
if n > 0:
print_range(n-1)  # this recursive call doesn't end the function
print(n)              # so this always runs, in both the base and recursive cases
``````

If you want the recursion to end the function, you either need to put it right at the end with no code following it, or you should use the `return` statement to stop from wherever you are. If your recursive function returns a value, you'll often want to return the value from the recursive call:

``````def my_sum(sequence, total=0):
if sequence:
return my_sum(sequence[1:], total+sequence[0])  # this time we return here
return total  # so this only runs in the base case (when the sequence is empty)
``````

While it's important to understand recursion if you're a beginner programmer, it's worth noting that Python is often much faster when you use loops to control repeated actions, rather than recursion. Some algorithms are still most easily implemented with recursion, but when you can easily translate some recursive code to instead use a loop, you probably should.