Установите часть лямбда-функции заранее, чтобы избежать повторного кода

Следующий метод сортировки отлично работает.

def sort_view_items(self):

    cs = self.settings.case_sensitive

    if self.settings.sort_by_file_name:
        sk = lambda vi: (vi.name if cs else vi.name.lower(), vi.group, vi.tab)

    elif self.settings.sort_by_folder:
        sk = lambda vi: (vi.folder, vi.name if cs else vi.name.lower())

    elif self.settings.sort_by_syntax:
        sk = lambda vi: (vi.syntax, vi.name if cs else vi.name.lower())

    elif self.settings.sort_by_indexes:
        sk = lambda vi: (vi.group, vi.tab)

    self.view_items.sort(key = sk)

Однако чувствительный к регистру раздел lambdas vi.name if cs else vi.name.lower() используется 3 раза, что раздражает мой повторяющийся кодовый ген.

Из интереса, может ли случайный аспект быть заранее установлен каким-либо образом, но без внесения permenant изменений в атрибут name или сделать это во временной копии списка view_items?

Например, я попытался использовать лямбда в лямбда, который, как я думал, не сработает, и, угадайте, что это не так. Хотя неожиданно синтаксис был принят (без исключений), он просто не привел к тому, что фактически была выполнена какая-либо сортировка.

def sort_view_items(self):

    cs = self.settings.case_sensitive

    name_lambda = lambda vi: vi.name if cs else vi.name.lower()

    if self.settings.sort_by_file_name:
        sk = lambda vi: (name_lambda, vi.group, vi.tab)

    ...

Ответ 1

Вам нужно позвонить name_lambda:

sk = lambda vi: (name_lambda(vi), vi.group, vi.tab)

В вашем фрагменте name_lambda определяется правильно, но он никогда не будет вызван.

Ответ 2

Это требует, чтобы вы добавили новое свойство "lower_name" в свой класс, но это одно изменение позволяет значительно упростить остальную часть кода.

from operator import attrgetter

class Things(object):
    @property
    def lower_name(self):
        return self.name.lower()

    def sort_view_items(self):
        name_field = "name" if self.settings.case_sensitive else "lower_name"

        if self.settings.sort_by_file_name:
            fields = (name_field, "group", "tab")
        elif self.settings.sort_by_folder:
            fields = ("folder", name_field)
        elif self.settings.sort_by_syntax:
            fields = ("syntax", name_field)
        elif self.settings.sort_by_indexes:
            fields = ("group", "tab")

        self.view_items.sort(key=attrgetter(*fields))

Ответ 3

Поскольку вы хотите использовать его в 3 из 4 условий, лучший способ отказаться от этого повторения, вычисляет имя в верхней части ваших условий if. Также вы можете использовать ключевое слово def, чтобы правильно создать функцию key и вернуть соответствующее значение, istead для определения функции каждый раз. В этом случае вы можете передать vi в key_func и вычислить name верхний уровень этой функции.

def sort_view_items(self):

    def key_func(vi):
        name = vi.name if self.settings.case_sensitive else vi.name.lower()
        if self.settings.sort_by_file_name:
            return name(vi), vi.group, vi.tab

        elif self.settings.sort_by_folder:
            return vi.folder,name(vi)

        elif self.settings.sort_by_syntax:
            return vi.syntax, name(vi)

        elif self.settings.sort_by_indexes:
            return vi.group, vi.tab

    self.view_items.sort(key=key_func)