Python: функция list () портит карту () - PullRequest
0 голосов
/ 24 сентября 2018

Я немного поиграл с функциями map() и filter() на python 3. Я попытался взять список и отфильтровать его, а затем на объекте фильтра выполнить функцию карты:

f = list(range(10))
print(f)
print('-----------')
y = filter(lambda a: a > 5, f)
print(list(y))
print(y)
print(type(y))
print('-----------')
x = map(lambda value: value+1, y)
print(list(y))
print(y)
print(type(y))
print('-----------')
print(list(x))
print(x)
print(type(x))

Результат:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-----------
[6, 7, 8, 9]
<filter object at 0x7f46db255ac8>
<class 'filter'>
-----------
[]
<filter object at 0x7f46db255ac8>
<class 'filter'>
-----------
[]
<map object at 0x7f46db3fc128>
<class 'map'>

Когда я закомментирую print(list(y)), он неожиданно работает хорошо.Вы сталкивались с этим?Что я делаю неправильно?Я запускаю Python 3.6.3 на Ubuntu.

Ответы [ 2 ]

0 голосов
/ 24 сентября 2018

Я согласен с ответом Роганьоша, но давайте посмотрим, смогу ли я добавить немного больше:

В функциях filter(), map() и reversed() немного запутано то, что они неt возвращает списки (как и следовало ожидать), но вместо этого возвращают итераторы.(Это указано в справочном тексте, который вы можете прочитать при вводе help(filter), help(map) и help(reversed).)

Так что теперь, когда вы знаете, что они возвращают итераторы вместо списков, вы можетеудивляться: почему это важно?Ну, итераторы предназначены для итерации за один раз (то есть, не более одного раза), как в цикле for, например for i in iterator:.И еще важно помнить, что после итерации итератора у него больше не осталось элементов для итерации .

Для иллюстрации рассмотрим следующий код:

backwards = reversed( [1, 2, 3, 4, 5] )   # creates an iterator; not a list!
myList = list(backwards)   # iterates over the iterator to create a list
print(myList)   # prints "[5, 4, 3, 2, 1]", as you'd expect
myList = list(backwards)   # nothing left to iterate over, so creates an empty list
print(myList)   # prints "[]" (an empty list)

Так что же делать, если вы хотите получить список из filter(), map() и reversed() вместо итератора?Что ж, вы можете сразу обернуть эти вызовы функций в list() и использовать этот результат, когда вам это нужно, например:

myList = list( reversed( [1, 2, 3, 4, 5] ) )
# Now use myList whenever you need it, without worrying that it will disappear.

Или вы можете заменить filter() и map() на списки,вот так:

f = list(range(10))
y = [a for a in f if a > 5]  # you can use this instead of filter()
x = [a + 1 for a in f]  # you can use this instead of map()

А что касается замены reversed()?Попробуйте это:

z = f[::-1]  # you can use this instead of reversed()

Возможно, вам интересно: если я могу использовать замены для filter(), map() и reversed(), зачем мне их использовать?

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

0 голосов
/ 24 сентября 2018

Итераторы и генераторы могут быть использованы только один раз.Когда вы вызываете list(y), он возвращает все значения в последовательности и затем исчерпывается.Когда вы попытаетесь просмотреть содержимое во второй раз, ничего не останется, так что вы получите пустой список.

Это более четко продемонстрировано с помощью:

f = list(range(10))
print(f)
print('-----------')
y = filter(lambda a: a > 5, f)
print(list(y))
print(list(y))

Какиедает:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-----------
[6, 7, 8, 9]
[] # Nothing to yield

Если вы хотите сохранить значения в y, вам нужно присвоить его имени:

y = list(filter(lambda a: a > 5, f))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...