In Python, is it considered better style to:
I will explain my question by way of a contrived example.
Suppose one writes a function, _sort_by_scoring, that takes two arguments: a scoring function and a list of items. It returns a copy of the original list sorted by scores based on each item's position within the original list. Two example scoring functions are also provided.
def _sort_by_score(scoring, items_list):
unsorted_scored_list = [(scoring(len(items_list), item_position), item) for item_position, item in enumerate(items_list)]
sorted_list = [item for score, item in sorted(unsorted_scored_list)]
return sorted_list
def _identity_scoring(items_list_size, item_position):
return item_position
def _reversed_scoring(items_list_size, item_position):
return items_list_size - item_position
The function _sort_by_score is never called directly; instead, it is called by other single-argument functions that pass a scoring function and their lone argument (a list of items) to _sort_by_scoring and return the result.
# Explicit function definition style
def identity_ordering(items_list):
return _sort_by_score(_identity_scoring, items_list)
def reversed_ordering(items_list):
return _sort_by_score(_reversed_scoring, items_list)
Obviously, this intent is better expressed in terms of function currying.
# Curried function definition style
import functools
identity_ordering = functools.partial(_sort_by_score, _identity_scoring)
reversed_ordering = functools.partial(_sort_by_score, _reversed_scoring)
Usage (in either case):
>>> foo = [1, 2, 3, 4, 5]
>>> identity_ordering(foo)
[1, 2, 3, 4, 5]
>>> reversed_ordering(foo)
[5, 4, 3, 2, 1]
Apparent advantages of the explicit function definition style:
Apparent advantages of curried function definition style:
For defining "useful" functions, which of the two styles is preferred? Are there other styles that are more idiomatic/Pythonic/etc.?
If you want to have the curried functions as part of a public interface, use explicit function definitions. This has the following additional advantages:
It is easier to assign a docstring to an explicit function definition. For partial()
functions, you would have to assign to the __doc__
attribute, which is somewhat ugly.
Real function definitions are easier to skim when browsing the module source.
I would use functools.partial()
in a similar way to lambda expressions, i.e. for locally needed throw-away functions.
In your particular example, I'd probably use neither, drop the leading underscores and call
sort_by_score(identity_scoring, foo)
which seems the most explicit to me.