«Отнаследовать» функцию от существующей в Python

Допустим, у нас есть список важных гостей. Он в легком беспорядке:

data = [
  "4 - Дуглас",
  "2 - Клер",
  "11 - Зоя",
  "1 - Френк",
  "31 - Питер",
]

Отсортируем:

>>> sorted(data)
['1 - Френк', '11 - Зоя', '2 - Клер', '31 - Питер', '4 - Дуглас']

Порядка не прибавилось — sorted() не знает, что здесь нужна числовая сортировка, а не алфавитная. Поможем ему:

def _key(src):
    parts = src.partition(" - ")
    return int(parts[0])

>>> sorted(data, key=_key)
['1 - Френк', '2 - Клер', '4 - Дуглас', '11 - Зоя', '31 - Питер']

Так хорошо! А чтобы добавить семантичности и не таскать везде дополнительный параметр key, создадим собственную функцию на основе sorted():

def natsorted(iterable, reverse=False):
    return sorted(iterable, key=_key, reverse=reverse)

>>> natsorted(data)
['1 - Френк', '2 - Клер', '4 - Дуглас', '11 - Зоя', '31 - Питер']

Есть и более лакончиный способ сделать это — через functools.partial():

import functools
natsorted = functools.partial(sorted, key=_key)

partial() создает новую функцию на основе существующей. При этом можно «зафиксировать» один или несколько параметров (мы зафиксировали key), разрешив менять остальные (iterable и reverse в нашем случае).

Таким образом, partial() помогает создавать узкоспециализированные функции на базе более универсальных.

Заметка из телеграм-канала «Oh My Py»