Это пример из книги Братта Слаткина

def sort_priority(values,   group):
    def helper(x):
        if  x   in  group:
            return  (0, x)
        return  (1, x)
    values.sort(key=helper)

Кроме того, они дали эти значения

numbers =   [8, 3,  1,  2,  5,  4,  7,  6]
group   =   {2, 3,  5,  7}
sort_priority(numbers,  group)
print(numbers)

И у нас есть

[2, 3,  5,  7,  1,  4,  6,  8]

Я не понимаю этот пример. Почему мы возвращаемся два раза и что на самом деле делает вспомогательная функция?

1
fabiano.mota 27 Авг 2017 в 10:33

4 ответа

Лучший ответ

Вы читаете функцию как:

def helper(x):
    if x in group:
        return (0, x)
    else:
        return (1, x)

Или, точнее,

def helper(x):
    return (x not in group, x)

Интуиция заключается в том, что sort принимает обратный вызов key, который вызывается для каждого элемента. Для каждого элемента вызывается helper, который возвращает кортеж (может быть (0, x) или (1, x) в зависимости от того, существует ли x в списке VIP).

Вы должны понимать, что кортежи сортируются на основе нескольких предикатов, то есть оба элемента в кортежах учитываются при определении порядка элементов. Это подразумевает, что элементы, для которых группа возвращает (0, x), будут упорядочены в первую очередь по сравнению с элементами, возвращающими (1, x), потому что 0 < 1.

После этого у нас есть две группы: группы с первым элементом 0 и группы с первым элементом 1. Все 0 элементы группы будут на первом месте, но порядок этих элементов зависит от второго элемента в кортежах - x. И похоже на 1 групповые элементы.


Для вашего ввода:

Group0: [2, 3, 5, 7]
Group1: [8, 1, 4, 6]

Ordering within Group0: [2, 3, 5, 7]
Ordering within Group1: [1, 4, 6, 8]

Overall ordering: [Group0, Group1]

Result:  [2, 3, 5, 7,    1, 4, 6, 8]
4
cs95 8 Июл 2018 в 19:39

Код легче понять, когда он написан без вложенных функций:

def helper(x):
    global group
    if x in group:
        return 0, x
    return 1, x


def sort_priority(values):
    values.sort(key=helper)


numbers = [8, 3, 1, 2, 5, 4, 7, 6]
group = {2, 3, 5, 7}
sort_priority(numbers)
print(numbers)

Теперь легко увидеть, что sort_priority() просто сортирует значения, вызывая функцию helper, которая создает порядок, присваивая значение каждому x.

Когда функция helper вызывается со значением, которое находится в group - она получает «более низкий» приоритет (ноль), а если значение не находится в group, она получает более высокий приоритет (один) ,

Более пристальный взгляд на helper действительно показывает:

def helper(x):
    global group
    if x in group:
        return 0, x  # <-- we're in the `if` so `x` gets zero 
    return 1, x      # <-- if we got here it means we didn't get into the `if` so `x` gets one

Таким образом, используя helper в качестве функции key в сортировке, мы получим и упорядочим списки, которые сначала помещают элементы, которые находятся в group, а затем только элементы, которых нет в { { Х3 } } :

[2, 3, 5, 7, 1, 4, 6, 8]
             ^
            The first item that is not in group
1
alfasin 27 Авг 2017 в 07:45

Обратите внимание, что первый оператор return находится внутри блока if. В Python всякий раз, когда функция сталкивается с оператором возврата, выполнение возвращается вызывающей стороне. В вашем примере два возврата - это всего лишь краткий способ избежать операторов if else. Когда определенное значение находится в группе, возвращается (0,x), а если условие if не выполняется, то возвращается (1,x).

1
Mortz 27 Авг 2017 в 07:41

Почему мы возвращаемся два раза?

Это не имеет ничего общего с замыканиями или вложенными функциями.

def helper(x):
    if  x  in  group:
        return  (0, x)
    return  (1, x)

Можно записать как

def helper(x):
    if  x   in  group:
        return  (0, x)
    else:        
        return  (1, x)

В любом случае, возвращаемое значение зависит от того, для чего вычисляется оператор if. Если это True, то (0, x) будет возвращено. Если это False, то (1, x) будет возвращено.

2
DeepSpace 27 Авг 2017 в 07:37