How functions works?

Why this function is behaving like a loop

def factorial(no):
    if no == 0:
        return 1
        return no * factorial(no - 1)

print("factorial of a number is:", factorial(8))

why this behaves like a loop, it thought it would return no*factorial(no-1) as 8*7.

And when I replace return with print() function it shows errror

def factorial(no):
    if no == 0:
        return 1
        print(no * factorial(no - 1))



Traceback (most recent call last):
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/", line 31, in <module>
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/", line 30, in start
    exec(open(mainpyfile).read(),  __main__.__dict__)
  File "<string>", line 7, in <module>
  File "<string>", line 5, in factorial
  File "<string>", line 5, in factorial
  File "<string>", line 5, in factorial
  [Previous line repeated 4 more times]
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'

[Program finished]

Can someone explain how print() and return work differently in function

It’s called “recursion” when a function calls itself.

Why do you think no * factorial(no - 1) is the same as 8 * 7? It’s 8 * factorial(7), not 8 * 7.

And factorial(7) is 7 * factorial(6), factorial(6) is 6 * factorial(5), and so on, until it gets to factorial(0), which is 1.

When you replace return ... with print ..., you’re not explicitly returning anything, so it returns None instead.

What will it do with factorial(2)? It'll want to do print(2 * factorial(1)).

--> What will it do with factorial(1)? It'll want to do print(1 * factorial(0)).

    --> What will it do with factorial(0)? It'll return 1.

    <-- So factorial(1) will do print(1 * 1) and then return None.

<-- And now you're trying to do print(2 * None).
1 Like