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.