I think it is the other way round:
keyiter+keybuffer- less verbose for user codekeymode- more verbose in user code, but could be more convenient to write derivatives as per above
Although I am not convinced about the above…
e.g. what would this do?
argsort([2, 1, 3], [3, 1, 2], 'iter')
And how does that make sense?
but I appreciate that one more argument needs to be cascaded and early error detection, for cases where sorted gets called far down the line is a bit more involved:
assert sum([v is not None for v in [key, keyiter, keybuffer]]) <= 1
Not catastrophic, but:
assert keymode in {'keyfunc', 'iter', 'inplace'}
is a bit quicker.
However, what you are trying to do with argsort will be tricky with both variations - it is not 1-to-1 relationship and mutability needs to be handled and adapted.
In essence, there are no xs. Only range(N) and key. However, key can be either:
IterableIterable+keyfunclistto be mutated in-place
I think production version of such will have to give up attempt to make strict equivalence with list.sort and just code it as the concept dictates and make use of list.sort efficiently:
def argsort(xs, key='iter', reverse=False):
if key != 'inplace':
if key != 'iter':
xs = map(key, xs)
xs = list(xs)
else:
assert isinstance(xs, list)
indices = range(len(xs))
# keymode
return sorted(indices, key=xs, keymode='inplace', reverse=reverse)
# keyiter / keybuffer
return sorted(indices, keybuffer=xs, reverse=reverse)
However, key as keyfunc in relation to list.sort is unnecessary confusion.
For list.sort, key makes sense as it has values to be sorted which are different than decorated key version.
While here, values don’t exist - they are range(N), thus:
def argsort(xs, reverse=False, inplace=False):
if not inplace:
xs = list(xs)
# keymode
return sorted(range(len(xs)), key=xs, keymode='inplace', reverse=reverse)
# keyiter / keybuffer
return sorted(range(len(xs)), keybuffer=xs, reverse=reverse)
If one wants to use keyfunc, then:
argsort(map(keyfunc, keys))
which leaves implementation simpler, usage more explicit and not much worse than previous:
argsort(keys, key=keyfunc)