# Independent sorting expectations; list.sort is a separate mutable operation.
source = [3, -2, 3, 0, -9, 1]
alias = source
print(sorted(source), source, alias is source, sorted(source) is source)
print(sorted(source, reverse=True), sorted(source, reverse=1))
print(sorted([]), sorted([7]), sorted('🙂éa'), sorted(b'cab'))
print(sorted(range(5, -2, -2)), sorted(iter([4, 1, 3])))
pairs = [('b', 2), ('a', 1), ('c', 2), ('d', 1)]
print(sorted(pairs, key=lambda pair: pair[1]))
print(sorted(pairs, key=lambda pair: pair[1], reverse=True))
print(sorted(pairs))

seen = []
def traced(value):
    seen.append(value)
    return abs(value)
print(sorted(source, key=traced, reverse=True))
print(seen)

remaining = iter([3, 1, 2])
def after_consumption(value):
    print('remaining', next(remaining, -1))
    return value
print(sorted(remaining, key=after_consumption))

original = [3, 1, 2]
def mutate_original(value):
    original.clear()
    return value
print(sorted(original, key=mutate_original), original)

class Item:
    def __init__(self, label, group):
        self.label = label
        self.group = group
items = [Item('a', 2), Item('b', 1), Item('c', 2)]
ordered = sorted(items, key=lambda item: item.group)
print([item.label for item in ordered], ordered[1] is items[0])

def make_key(offset):
    return lambda value: abs(value - offset)
print(sorted([4, 0, 2, 5], key=make_key(3)))

def fail(value):
    if value == 2:
        raise ValueError('key failed')
    return value
try:
    sorted([3, 2, 1], key=fail)
except ValueError as error:
    print(str(error))
try:
    sorted([], reverse=2147483648)
except OverflowError as error:
    print(str(error))
print(sorted([2, 1], key=None, reverse=-2147483648))
order = sorted
print(order([2, 1]), min(pairs, key=lambda pair: (pair[1], pair[0])))
class Keys:
    def score(self, value):
        return -value
print(sorted([1, 3, 2], key=Keys().score))
