Как использовать фильтр, карту и уменьшить в Python 3
filter
, map
и reduce
отлично работают в Python 2. Вот пример:
>>> def f(x):
return x % 2 != 0 and x % 3 != 0
>>> filter(f, range(2, 25))
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x):
return x*x*x
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>> def add(x,y):
return x+y
>>> reduce(add, range(1, 11))
55
Но в Python 3 я получаю следующие выходы:
>>> filter(f, range(2, 25))
<filter object at 0x0000000002C14908>
>>> map(cube, range(1, 11))
<map object at 0x0000000002C82B70>
>>> reduce(add, range(1, 11))
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
reduce(add, range(1, 11))
NameError: name 'reduce' is not defined
Я был бы признателен, если бы кто-нибудь мог объяснить мне, почему это так.
Скриншот кода для большей ясности:
![ИДЕННЫЕ сеансы Python 2 и 3 бок о бок]()
Ответы
Ответ 1
Вы можете прочитать об изменениях в Что нового в Python 3.0. Вы должны внимательно прочитать его при переходе с 2.x на 3.x, так как многое изменилось.
Весь ответ здесь - цитаты из документации.
Представления и итераторы вместо списков
Некоторые известные API больше не возвращают списки:
- [...]
-
map()
и filter()
возвратить итераторы. Если вам действительно нужен список, быстрое исправление, например. list(map(...))
, но лучше исправить часто использовать понимание списка (особенно когда исходный код использует лямбда), или переписывать код, чтобы он вообще не нуждался в списке. Особенно сложно использовать map()
для побочных эффектов функции; правильное преобразование состоит в использовании регулярного цикла for
(так как создание списка будет просто расточительным). - [...]
Builtins
- [...]
- Удалено
reduce()
. Используйте functools.reduce()
, если вам это действительно нужно; однако в 99% случаев явный цикл for
более читабельен. - [...]
Ответ 2
Функциональность map
и filter
была намеренно изменена для возврата итераторов, и сокращение было удалено из встроенного и помещено в functools.reduce
.
Итак, для filter
и map
вы можете обернуть их с помощью list()
, чтобы увидеть результаты, как и раньше.
>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> list(filter(f, range(2, 25)))
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> list(map(cube, range(1, 11)))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>> import functools
>>> def add(x,y): return x+y
...
>>> functools.reduce(add, range(1, 11))
55
>>>
Рекомендация теперь заключается в том, что вы заменяете использование карты и фильтра выражениями генераторов или пониманием списков. Пример:
>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> [i for i in range(2, 25) if f(i)]
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> [cube(i) for i in range(1, 11)]
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>>
Говорят, что для циклов в 99% случаев легче читать, чем уменьшать, но я просто придерживаюсь functools.reduce
.
Изменить: 99-процентная фигура вытягивается непосредственно из Что нового в Python 3.0, автором которой является Гвидо ван Россум.
Ответ 3
В качестве дополнения к другим ответам это звучит как прекрасный вариант использования для менеджера контекста, который будет переназначать имена этих функций тем, которые возвращают список, и вводят reduce
в глобальное пространство имен.
Быстрая реализация может выглядеть так:
from contextlib import contextmanager
@contextmanager
def noiters(*funcs):
if not funcs:
funcs = [map, filter, zip] # etc
from functools import reduce
globals()[reduce.__name__] = reduce
for func in funcs:
globals()[func.__name__] = lambda *ar, func = func, **kwar: list(func(*ar, **kwar))
try:
yield
finally:
del globals()[reduce.__name__]
for func in funcs: globals()[func.__name__] = func
С использованием, которое выглядит так:
with noiters(map):
from operator import add
print(reduce(add, range(1, 20)))
print(map(int, ['1', '2']))
Какие принты:
190
[1, 2]
Только мои 2 цента: -)
Ответ 4
Поскольку reduce
метод был удален из встроенной функции от Python3, не забудьте импортировать functools
в вашем коде. Пожалуйста, посмотрите на фрагмент кода ниже.
import functools
my_list = [10,15,20,25,35]
sum_numbers = functools.reduce(lambda x ,y : x+y , my_list)
print(sum_numbers)
Ответ 5
Вот примеры функций Фильтр, Карта и Сокращение.
числа = [10,11,12,22,34,43,54,34,67,87,88,98,99,87,44,66]
//Фильтр
oddNumbers = list (фильтр (лямбда x: x% 2! = 0, числа))
печать (oddNumbers)
//Карта
multiplyOf2 = список (карта (лямбда х: х * 2, цифры))
печать (multiplyOf2)
//Уменьшить
Функция Reduce, поскольку она обычно не используется, была удалена из встроенных функций в Python 3. Она по-прежнему доступна в модуле functools, поэтому вы можете сделать следующее:
от импорта functools
sumOfNumbers = уменьшить (лямбда х, у: х + у, числа)
печать (sumOfNumbers)