Я немного играл с функциями 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.
Итераторы и генераторы могут потребляться только один раз. Когда вы вызываете 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))
y = list(filter(lambda a: a > 5, f)
затем print(y)
сейчас, когда мы хотим использовать y
в будущем, нам не нужно использовать list
каждый раз, когда мы вызываем y
list()
заключается в том, что второй выведет пустой список
Я согласен с ответом roganjosh, но давайте посмотрим, смогу ли я добавить немного дополнительного:
Что немного запутывает функции filter()
, map()
и reversed()
это то, что они не возвращают списки (как и ожидалось), а вместо этого возвращают итераторы. (Это указано в тексте справки, который вы можете прочитать при вводе help(filter)
, help(map)
и help(reversed)
.)
Итак, теперь, когда вы знаете, что они возвращают итераторы вместо списков, вам может быть интересно: почему это имеет значение? Ну, итераторы должны повторяться один раз (то есть не более одного раза), например, в for-loop, например, for я 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()
, зачем мне их использовать?
Ответ заключается в том, что иногда вам нужно будет фильтровать, сопоставлять или перетаскивать огромный список, а создание другого (огромного) списка только для циклы/повтора будет очень расточительным и трудоемким. Таким образом, возврат итератора предотвращает использование еще одного огромного фрагмента памяти - просто знайте, что, когда итератор расходуется (то есть итерируется), его информация исчезла.
list()
дляy
потребляет итератор. Итераторы могут использоваться только один раз. Когда вы вызываете выходy
во второй раз вprint()
не остается значений для выхода. Вы можете увидеть это просто с помощью:y = filter(lambda a: a > 5, f); print(list(y)); print(list(y))