Советы по использованию функции карты с помощью setitem

#python #dictionary

Вопрос:

Я изо всех сил пытаюсь понять сценарий из «Книги на Python». Скрипт удаляет дубликаты из списка, помещая каждый элемент в дикт в качестве ключа (например, со 'none' значением as), а затем возвращает dict.keys() . Сценарий выглядит следующим образом:

 from operator import setitem
def distinct(l):
    d = {}
    map(setitem, (d,)*len(l), l, [])
    return d.keys()
 

Я запустил скрипт, передав список, содержащий дубликаты, в distinct() :

 li = [1, 5, 6, 1, 8]
x = distinct(li)
print(x)
 

Однако, когда я запускаю скрипт и печатаю результат, я просто получаю:

 dict_keys([])
 

Может ли кто-нибудь привести мне пример того, как я могу запустить distinct() функцию, чтобы получить какой-то значимый результат? Также, пожалуйста, кто-нибудь может объяснить, как функция карты работает с внутренней setitem функцией. Я читал об setitem этом , но я не уверен, как это здесь работает. Меня смущает первый аргумент, чтобы setitem :

 (d,)*len(l)
 

Ответ №1:

Как написано, distinct не может работать в Python 3, как map и класс, который в данном случае возвращает итерацию, которая будет вызываться setitem по требованию при повторении. Поскольку возвращаемое значение игнорируется, setitem оно никогда не будет вызвано.

В Python 2 map была функция, которая действовала во многом как понимание списка: она возвращала список возвращаемых значений при вызове setitem элементов заданных итераций. Но никогда не считалось хорошей практикой использовать map (или понимать список) просто для побочного эффекта функции.

Если вас не волнует результирующая последовательность или список, используйте правильный for цикл вместо создания map экземпляра, который никогда не повторяется.

 def distinct(l):
    d = {}
    for k in l:
        d[k] = None
    return list(d)
 

Или используйте понимание под диктовку:

 def distinct(l):
    return list({k: None for k in l})
 

Цель (d,)*len(l) состояла в том , чтобы создать последовательность ссылок на d , чтобы каждый вызов setitem изменялся одинаково dict .

Адаптация моего первого примера для использования setitem будет выглядеть так

 def distinct(l):
    d = {}
    for k in l:
        setitem(d, k, None)
    return list(d)
 

Обратите внимание, что list(map(setitem, (d,)*len(l), l, [])) это никогда бы ничего не сделало. [] была третья итерация, содержимое которой, а не сам список, будет использоваться в качестве третьего аргумента setitem . map выполняется только до тех пор, пока не будет исчерпан самый короткий из повторяемых элементов, и пустой список будет немедленно исчерпан.