Python Forum
Why this code does not go into an infinite loop? - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Why this code does not go into an infinite loop? (/thread-38850.html)



Why this code does not go into an infinite loop? - 2367409125 - Dec-02-2022

import time
def time_master(func):
    def call_func():
        print("start program")
        start = time.time()
        func()
        stop = time.time()
        print(f"it take {stop - start}second.")

    return call_func


def myfunc():
    time.sleep(2)
    print('I love fishc')
myfunc=time_master(myfunc)
myfunc()
Hey, I am learning python, and I am confused with this code, this code create some functions to detect the times of runing other functions. However, in this case, at the end of the code, myfunc should equal to time_master(myfunc) right? so I believe when myfunc() recall the time_master function, in the time_master function -call_func() part, the myfunc function will be run again and start another time_master(myfunc) . Which will lead into an infinite loop, but it actually does not, can someone explain the reasons for me? thanks Rolleyes


RE: Why this code does not go into an infinite loop? - bowlofred - Dec-02-2022

(Dec-02-2022, 05:32 PM)2367409125 Wrote: myfunc should equal to time_master(myfunc) right?

myfunc is assigned the output of time_master(myfunc). The output of that call is the call_func object.

time_master is called once (on line 16). It is not called when line 17 is executed.


RE: Why this code does not go into an infinite loop? - deanhystad - Dec-02-2022

This is all about contexts and closures.

I added some print statements to help track what is going on.
import time
def time_master(func):
    def call_func():
        print("start program")
        print("D", func)
        start = time.time()
        func()
        stop = time.time()
        print(f"it take {stop - start}second.")

    print("B", func)
    return call_func


def myfunc():
    time.sleep(2)
    print('I love fishc')

print("A", myfunc)
myfunc=time_master(myfunc)
print("C", myfunc)
myfunc()
Output:
A <function myfunc at 0x000001BE71C35360> B <function myfunc at 0x000001BE71C35360> C <function time_master.<locals>.call_func at 0x000001BE71C353F0> start program D <function myfunc at 0x000001BE71C35360> I love fishc it take 2.001746416091919second.
A: In the global context you define a function <function myfunc at 0x000001BE71C35360>. You assign this function to a variable named myfunc.

B: You pass this function as an argument to time_master. This creates a variable named func that exists inside the function time_master. Unlike most function variables, this one hangs around because we have a reference to the variable. Python creates a closure, kind of a persistent bubble of context that is used when we call myfunc() later on.

C: You assign the value returned by time_master <function time_master.<locals>.call_func at 0x000001BE71C353F0> to a variable named myfunc. myfunc now rferences time_master.call_func. You can no longer use myfunc to call the original function referenced by that variable.

D: You use the variable myfunc to call the time_master.call_func() function. This in turn calls the original myfunc function, not the function referenced by the myfunc variable.

Unlike variables in C++, myfunc is just a name that your program can use to reference python objects. It is not storage. It has no type. It is like the key in a dictionary. In this example it references a function , but I could write "myfunc = 42" and that would be a valid Python statement.