#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
выполняется только до тех пор, пока не будет исчерпан самый короткий из повторяемых элементов, и пустой список будет немедленно исчерпан.