Сортировка объектов datetime в python

Задача заключается в подсчете времени, в которое горит лампочка, пока за ней смотрит наблюдатель. Из входных данных - отрезки включения и выключения лампочки, а также время наблюдения. Код выглядит так (знаю, громоздко):

from datetime import datetime
from typing import List, Optional

def sum_light(els: List[datetime],
              start_watching: Optional[datetime] = None,
              end_watching: Optional[datetime] = None) -> int:
    if start_watching is None:
        start_watching = els[0]
    if end_watching is None:
        end_watching = datetime.max
    els = sorted(els + [start_watching] + [end_watching])
    start = els.index(start_watching)
    end = els.index(end_watching)
    if start_watching is not None and end_watching is None:
        return int(sum((on - off).total_seconds() for off, on in
                   zip(els[start + (start % 2 == 0)::2], els[start + (start % 2 == 0) + 1::2])))
    elif start_watching is None and end_watching is not None:
        return int(sum((on - off).total_seconds() for off, on in
                   zip(els[:end + 1:2], els[1:end + 1:2])))
    elif start_watching is not None and end_watching is not None:
        return int(sum((on - off).total_seconds() for off, on in
                   zip(els[start + (start % 2 == 0):end + 1:2], els[start + (start % 2 == 0) + 1:end + 1:2])))
    else:
        return int(sum((on - off).total_seconds() for off, on in
                   zip(els[::2], els[1::2])))


if __name__ == "__main__":
    print("Example:")
    print(
          sum_light(
                    [
                      datetime(2015, 1, 12, 10, 0, 0),
                      datetime(2015, 1, 12, 10, 0, 10),
                    ],
                    datetime(2015, 1, 12, 10, 0, 0),
                    datetime(2015, 1, 12, 10, 0, 10),
                   )
         )

Следующий этап задачи - несколько лампочек (к входным данным добавляется номер лампочки, и теперь это объекты типа Tuple[datetime, int]. В коде могут быть как объекты tuple, так и просто объекты datetime, которые должны пониматься как первая лампочка (без индекса)).Код такой:

def sum_light(
              els: List[Union[datetime, Tuple[datetime, int]]],
              start_watching: Optional[datetime] = None,
              end_watching: Optional[datetime] = None) -> int:
    if start_watching is None:
        start_watching = els[0]
    if end_watching is None:
        end_watching = datetime.max
    els = [(elem, 1) if type(elem) is datetime else elem for elem in els] # Здесь привожу все элементы к общему виду
    els = sorted(els + [start_watching] + [end_watching], key=lambda x: (x[0], x[1]))

Но теперь, когда я пытаюсь отсортировать список по объекту datetime и индексу, интерпретатор ругается:

els = sorted(els, key=lambda x: x[0])

TypeError: 'datetime.datetime' object is not subscriptable

Почему в первом случае код спокойно отсортировал список по datetime, а во втором выскакивает ошибка?


Ответы (1 шт):

Автор решения: Spider_Godess_Adept

Досконально изучив возможности сортировки, понял, что кортежи можно отсортировать с помощью модуля operator. Задав оператору itemgetter() второй объект кортежа, а именно число (в моем случае номер лампочки), я смог отсортировать список так, чтобы включение и выключение каждой лампочки шло друг за другом, что дает мне возможность узнать время работы лампочки, поочередно вычитая время выключения из времени включения с помощью zip.

→ Ссылка