Given the following python code...
from functools import partial
def run_n( func = None, count = 1 ):
print( "func", func )
print( "count", count )
if func is None:
return partial( run_n, count = count )
def wrapper():
for _ in range( count ):
func()
return wrapper
@run_n( count = 2 )
def func():
print( "Hello" )
func()
I get the following output..
func None
count 2
func <function func at 0x7f6b45572ca0>
count 2
Hello
Hello
My question is, give that the first invocation of the run_n
decorator has func
None, how does the second invocation acquire func
as the right value. I'll add that this code, less my prints, was acquired from the public source code. It seems to me that I lack the understanding of how partial
works but I still can't see how func
suddenly acquires a value.
First, run_n gets called with func=None
and n=2
. Since func
is None
, it will take the first branch of the if statement. partial
then creates, and returns, an anonymous function that behaves as if it was defined like this:
def anonymous(*args, **kwargs):
return run_n(*args, count=2, **kwargs)
Then that function gets called with the function being defined (i.e, the function printing "hello") as its first argument. This immediately calls
run_n(<func-printing-hello>,count=2)
This time, run_n
has been given a func
argument, and returns the wrapper function that calls func-printing-hello n times. This wrapper, eventually, is what gets assigned to the global func
name.