Как использовать фильтр, карту и уменьшить в 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)