Currently, the only way to reliably call max()
is with an iterable, and one must work around the issue by adding a level of indirection using a new function:
def max_indirected(*args, **kwargs):
return max(args, **kwargs)
Without this sort of solution, things get complicated when one attempts to unpack multiple (possibly empty) lists and use the unpacked lists as arguments to max()
:
list1, list2, list3 = [], [1], [] # results from queries or an API or whatever
max(*list1, *list2, *list3) # max of all items in these lists, except this doesn't work as expected
Instead, one must work around this issue using something like max_indirected()
above or the following
max(max(lst, default=0) for lst in (list1, list2, list3))
Then you have the case where you are using unpacking and want a single list to be treated as the unit of comparison with the key, not as an iterable containing multiple values:
list4 = [1, 2]
lists = [list4]
# return list of the longest length,
# except this calls max([1, 2], key=len),
# and 'int' cannot be used with len().
max(*lists, key=len)
# Workaround:
lists.append([])
max(*lists, key=len)
I’d call this a violation of “simple is better than complex” because max(1)
should work the same way max(1, 2)
currently does, and max([1], key=func)
should behave like max([1], [2], key=func)
.
That is a much more intuitive behavior.
In my mind, a good solution would be to separate the max(iterable[, default, key])
and max(arg1, *args[, key])
forms, perhaps deprecating the former with a movement into the itertools module and retaining the latter in the builtins module.
Note that the same solution should be also applied in the case of the min()
function since it suffers from the same issue.