Лямбда-функция Python для сортировки списка по словарю

Приведенные ниже примеры кодов извлекают все запущенные процессы и распечатывают их. Они написаны на основе третьего примера здесь и последнего из здесь. Проблема в том, что я не могу понять, почему только первый извлекает процесс, отсортированный по желанию.

Я думаю, что это связано с конструкцией функции lambda. Но правильно работающий образец, первый, похоже, смешивает локальную переменную p оператора for со словарем p.dict, что заставляет меня застрять.

Первый образец:

import psutil

procs = []

for p in psutil.process_iter():
    try:
        p.dict = p.as_dict(['pid', 'name'])
    except psutil.NoSuchProcess:
        pass
    else:
        procs.append(p)

processes = sorted(procs, key=lambda p: p.dict['name'], reverse=False)

print(processes)

Второй образец:

import psutil

procs = []

for proc in psutil.process_iter():
    try:
        procs_dic = proc.as_dict(['pid', 'name'])
    except psutil.NoSuchProcess:
         pass
    else:
        procs.append(proc)

processes = sorted(procs, key=lambda ordem: procs_dic['name'], reverse=False)

print(processes)

person Rodrigo Remedio    schedule 04.11.2016    source источник


Ответы (3)


Лямбда вашего второго фрагмента кода ищет 'name' в том же словаре, независимо от того, какой объект он передал; как это могло работать?

Ваш третий, кажется, даже не пытается сортировать процессы; Я не уверен, какое это имеет отношение к вопросу.

Изменение, которое вы внесли, чтобы превратить первый фрагмент во второй, очевидно, вызвано вашей заботой о том, чтобы первый

кажется, смешивает локальную переменную p оператора for со словарем p.dict

и я был бы рад помочь, но, боюсь, я не понимаю, в чем проблема, которую вы видите. Возможно, поможет следующее? Здесь есть две переменные с именами p. Первый используется в цикле по процессам; каждый раз в цикле его значением является объект процесса, и мы присваиваем этому объекту процесса атрибут dict, содержащий запись для 'name'. Второй — аргумент вашей анонимной функции (лямбда): его значение также всегда является объектом процесса. Вы могли бы дать им разные имена, если хотите, и это ничего не сломает, но на самом деле я думаю, что это и так понятнее: в этом маленьком фрагменте кода p — это то, что вы называете переменной, значение которой является объектом процесса. Но ничего не "перепутывается".

person Gareth McCaughan    schedule 04.11.2016
comment
На самом деле, я изменил предпоследнюю строку на processes = sorted(procs, key=lambda ordem: ordem.dict['name'], reverse=False), следуя совету @JordanMcQueen. Однако я смог выполнить задачу только после изменения на proc.dict = proc.as_dict(['pid', 'name']) строки после try. - person Rodrigo Remedio; 04.11.2016
comment
Верно. Таким образом, после этого у вас будет точно такой же код, как и в первом фрагменте, за исключением того, что вы переименовали одну из переменных с именем p в proc, а другую в ordem. - person Gareth McCaughan; 04.11.2016

Попробуйте использовать словарь, отображающий Processes на словари, содержащие их информацию.

proc_dict = {}
for proc in psutil.process_iter():
    try:
        proc_dict[proc] = proc.as_dict(['name', 'pid'])
    except psutil.NoSuchProcess:
        continue

Затем отсортируйте по значению name словаря для этого процесса.

print(*sorted(proc_dict, lambda x: proc_dict[x]['name']))
person Patrick Haugh    schedule 04.11.2016

В первом примере функция lambda принимает некоторую переменную p и возвращает p.dict['name']. Вы можете изменить здесь p на x или как хотите: это просто заполнитель.

Во втором примере, key=lambda ordem: procs_dic['name'], reverse=False), lambda принимает что-то с именем ordem, а затем снова и снова возвращает только procs_dic['name'].

Ключ работает в sorted следующим образом: когда он перебирает элементы и сортирует их, он вызывает lambda для каждого элемента, чтобы определить, по какому значению его сортировать.

Я предполагаю, что вы хотите, чтобы строка кода sorted во втором примере выглядела так:

processes = sorted(procs, key=lambda x: x.name(), reverse=False)

Обратите внимание, что Process.name() возвращает имя процесса.

person Jordan McQueen    schedule 04.11.2016