Reputation: 1595
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.
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
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
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
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:
'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!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