Search code examples
pythonfunctional-programming

How can a function takes another function WITH arguments, as a parameter?


def Wrapper(func):
  def MyPrint(message):
    print('Hello ' + message)
  
  func(MyPrint)

Wrapper(lambda my_print: my_print('world'))

I'm confused of the above code. I get that a function can take another function as parameter and use func() to invoke it, but how can Wrapper(lambda my_print: my_print('world')) call the inner function MyPrint? The func is a parameter, and the lambda my_print: my_print('world') is its argument, but somehow the argument seems to utilizes (penatrate through) an inner function inside Wrapper.

This is a very common pattern in JavaScript but confuses me. I think an explaination of what happened in detail might help.


Solution

  • (lambda my_print: my_print('world') doesn't call MyPrint directly; MyPrint is passed as its argument in func(MyPrint).

    Try the substitution method:

    Wrapper(lambda my_print: my_print('world'))
    

    ---> func is bound to lambda my_print: my_print('world') in the body of Wrapper:

    def MyPrint(message):
        print('Hello ' + message)
      
      (lambda my_print: my_print('world'))(MyPrint)
    

    --->

    my_print is bound to MyPrint in the body of the lambda:

    def MyPrint(message):
        print('Hello ' + message)
      
      MyPrint('world')
    

    Addendum: the same, but with a non-local function and no lambda, in case that makes it clearer:

    def GreetingPrinter(message):
        print('Hello ' + message)
    
    def Wrapper(func):
      func(GreetingPrinter)
    
    def PrintWithWorld(printer):
        printer('World')
    
    Wrapper(PrintWithWorld)