Dave Kalu
Dave Kalu

Reputation: 1595

Executing higher-order functions

I'm learning the concepts of first class functions and closures in Python and I was curious to know:

Given a higher-order function:

def html_tag(tag):
    def wrap_text(text):
        print("<{0}>{1}</{0}>".format(tag, text))
    return wrap_text
  1. What's the difference between these two approaches of executing higher-order functions.
  2. Are there any advantages of using one over the other.
  3. What is the best way to execute a higher-order function in a program.

1.

print_h1 = html_tag('h1')
print_h1('Test Headline')
print_h1('Another Headline')

2.

html_tag('h1')('Test Headline')
html_tag('h1')('Another Headline')

Upvotes: 0

Views: 303

Answers (3)

Barmar
Barmar

Reputation: 781098

In the example you give, there's no difference in the result. The second way is less efficient, since you're creating an equivalent function multiple times, which is redundant.

It becomes more relevant when you have functions that keep state between runs.

def counting_tag(tag):
    counter = 0
    def wrap_text(text):
        nonlocal counter
        counter += 1
        print("<{0}>{1}. {2}</{0}>".format(tag, counter, text))

Every time you call counting_tag() it will return a function with the counter reset back to 0.

print_h1 = counting_tag('h1')
print_h1('Test Headline')
print_h1('Another Headline')

This will print

1. Test Headline
2. Another Headline

But if you do it the second way:

counting_tag('h1')('Test Headline')
counting_tag('h1')('Another Headline')

you'll get

1. Test Headline
1. Another Headline

Upvotes: 1

awarrier99
awarrier99

Reputation: 3855

The only advantage I can think of is that by assigning the return value of html_tag to a variable in the first example, you prevent the code from having to execute again and return a new function each time. Whereas in your second example, you are calling html_tag directly and it will produce a new function reference each time, which will result in a decrease in performance.

Depends on your usage, but if you're passing in the same argument to html_tag, then I would go with your first example. But if you need to use a different tag, then obviously you would have to re-call html_tag again with a different argument.

In terms of the references to the function, this could be important, for example, if you were for some reason storing the function in a dict, so you wouldn't be able to lookup the function as a key unless you keep around a reference to the same function (as in your first example)

Upvotes: 1

Samwise
Samwise

Reputation: 71464

The reason you'd have a higher order function would typically be so that you could easily generate named helper functions like print_h1, as in your first example. This has two benefits:

  1. You avoid repeating the 'h1' string. Any time you have to copy and paste a string literal multiple places, it's an invitation for a bug to happen due to a typo!
  2. Less typing. (This is more like a secondary benefit of not repeating yourself.)

If you were going to re-invoke html_tag each time, as in your second example, making a higher order function offers no benefit over simply doing:

def html_tag(tag, text):
    print("<{0}>{1}</{0}>".format(tag, text))


html_tag('h1', 'Test Headline')
html_tag('h1', 'Another Headline')

Upvotes: 1

Related Questions