Python 3에서 필터, 맵 및 축소를 사용하는 방법


321

filter, map그리고 reduce완벽하게 파이썬 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

그러나 파이썬 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

누군가 이것이 왜 그런지 설명해 주시면 감사하겠습니다.

더 명확하게하기위한 코드 스크린 샷 :

파이썬 2와 3의 유휴 세션


1
간단히 말해 list는 유일한 데이터 유형이 아닙니다. 목록을 원한다면 목록을 원한다고 가정하십시오. 그러나 대부분의 경우 어쨌든 다른 것을 원합니다.
Veky

답변:


346

Python 3.0의 새로운 기능 변경 사항에 대해 읽을 수 있습니다 . 로트가 많이 변경되었으므로 2.x에서 3.x로 이동할 때 반드시 읽어야합니다.

여기에 전체 답변은 문서에서 인용 한 것입니다.

목록 대신보기 및 반복자

잘 알려진 일부 API는 더 이상 목록을 반환하지 않습니다.

  • [...]
  • map()filter()반복자를 돌려줍니다. 실제로 목록이 필요한 경우 빠른 수정은 예를 들어 list(map(...))더 나은 수정은 종종 목록 이해 (특히 원본 코드가 람다를 사용하는 경우)를 사용하거나 코드를 다시 작성하여 목록이 전혀 필요하지 않은 것입니다. map()기능의 부작용에 대해 특히 까다로운 것이 발생합니다. 올바른 변환은 정기적 인 for루프 를 사용하는 것입니다 (목록을 작성하는 것은 낭비이기 때문에).
  • [...]

내장

  • [...]
  • 제거되었습니다 reduce(). functools.reduce()정말로 필요한 경우 사용하십시오 . 그러나 명시 적 for루프가 더 읽기 쉬운 시간의 99 %입니다 .
  • [...]

21
추가 list(map(...) 어디서나 .. 세계 가독성을 돕는 것이 ... 것이 얼마나 python기능 콤비의 프로그레시브 / 스트리밍 응용 프로그램을 처리 할 수없는 것. 다른 언어 컬렉션에 대해 수십 개의 작업을 연속으로 연결할 수 있으며 읽을 수 있습니다. 여기? 무엇을 원하십니까 in?
javadba

11
명령형 컨텍스트에서 작업하는 경우 for-loop가 더 읽기 쉬운 옵션 일 수 있습니다. 그러나 기능적 맥락을 선호하는 데에는 충분한 이유가 있습니다. 그리고 절차 상으로 돌아 가기 위해 그 점을 깨는 것은 꽤 못생긴 일입니다.
MatrixManAtYrService

2
@javadba "스트리밍 애플리케이션"에서 list호출 을 추가해야 합니까? "스트리밍"의 의미는 "목록이 전혀 생성되지 않고 다음 요소로 넘어 가기 전에 입력의 각 요소를 완전히 처리하십시오"라고 생각했습니다.
Imperishable Night

@MatrixManAtYrService python 2 동작이 필요한 것이 확실하다면 언제든지 재정의 할 수 있습니다 map.
Imperishable Night

6
나는 여전히 가독성 인수가 그러한 변화로 이어지는 방법을 이해할 수 없습니다. 성능상의 이유로 이해한다면 ...
Minato

86

의 기능 map과는 filter의도적 반복자를 반환하도록 변경되었으며,되는 것을 제거 줄일 A의 내장에 위치 functools.reduce.

for 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]
>>>

그들은 for 루프가 줄어든 것보다 99 % 더 읽기 쉽다고 말합니다 functools.reduce.

편집 : 99 % 수치는 Guido van Rossum이 작성한 What 's New in Python 3.0 페이지 에서 직접 가져온 것 입니다.


5
목록 이해에서 추가 기능을 작성할 필요가 없습니다. 그냥 사용[i*i*i for i in range(1,11)]
Xiao

2
당신은 절대적으로 맞습니다. 필터 / 맵 예제와 비슷하게 보이도록 목록 이해 예제에서 함수를 유지했습니다.
Joshua D. Boyd

5
i ** 3은 또한 i * i * i와 같습니다
Breezer

5
@Breezer는 실제로 및 (또는 이와 유사한 것) i**3을 호출 합니다. 정수는 중요하지 않지만 숫자가 많은 숫자 / 사용자 정의 클래스는 다른 결과를 생성 할 수도 있습니다. i.__pow__(3)i*i*i i.__mul__(i).__mul__(i)
syntonym

1
우리는 "Guido 의사 결정 X"가 들릴 때마다 고통 이 결과라고 생각합니다. 이것은 파이썬에서 이미 장황한 list(list(list(.. )))것을 수행 하는 좋은 예 입니다.
javadba

12

다른 답변에 대한 부록으로,이 함수의 이름을 목록을 반환 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 센트 :-)


1
python언어로 엉망입니다 -하지만 V의 우수한 라이브러리에 좋은있다 : numpy, pandas, statsmodels및 네이티브 언어의 고통을 줄이기 위해 여기 보여처럼 ...... 나는 편의 라이브러리를 buliding했던 친구 -하지만 에너지를 잃고하지 않으려 고했다 data.frame/ 에서 멀어 datatable지거나 xarray. 그러나 시도를위한 kudos ..
javadba

7

때문에 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)

2

다음은 필터, 맵 및 축소 기능의 예입니다.

숫자 = [10,11,12,22,34,43,54,34,67,87,88,98,99,87,44,66]

//필터

oddNumbers = list (필터 (람다 x : x % 2! = 0, 숫자))

print (oddNumbers)

//지도

multiplyOf2 = list (맵 (람다 x : x * 2, 숫자))

인쇄 (multiplyOf2)

//줄이다

reduce 함수는 일반적으로 사용되지 않기 때문에 Python 3의 내장 함수에서 제거되었습니다. functools 모듈에서 계속 사용할 수 있으므로 다음을 수행 할 수 있습니다.

functools에서 가져 오기 감소

sumOfNumbers = 축소 (lambda x, y : x + y, 숫자)

print (sumOfNumbers)


0

지도, 필터링 및 축소의 장점 중 하나는 복잡한 것을 수행하기 위해 함께 "체인"할 때 이들이 가독성이 있다는 것입니다. 그러나 내장 구문은 읽을 수 없으며 모두 "뒤로"입니다. 따라서 PyFunctional패키지 ( https://pypi.org/project/PyFunctional/ )를 사용하는 것이 좋습니다 . 다음은 두 가지를 비교 한 것입니다.

flight_destinations_dict = {'NY': {'London', 'Rome'}, 'Berlin': {'NY'}}

PyFunctional 버전

매우 읽기 쉬운 구문. 당신은 말할 수 있습니다 :

"나는 일련의 비행 목적지를 가지고있다. 도시가 dict 값에 있으면 dict 키를 얻고 싶다. 마지막으로, 프로세스에서 생성 한 빈리스트를 걸러 내라."

from functional import seq  # PyFunctional package to allow easier syntax

def find_return_flights_PYFUNCTIONAL_SYNTAX(city, flight_destinations_dict):
    return seq(flight_destinations_dict.items()) \
        .map(lambda x: x[0] if city in x[1] else []) \
        .filter(lambda x: x != []) \

기본 파이썬 버전

모두 거꾸로입니다. 당신은 말할 필요가있다 :

"좋아요,리스트가 있어요. 빈리스트를 걸러 내고 싶어요. 왜? 도시가 dict 값에 있으면 먼저 dict 키를 얻었 기 때문입니다. 아, 제가하고있는리스트는 flight_destinations_dict입니다. "

def find_return_flights_DEFAULT_SYNTAX(city, flight_destinations_dict):
    return list(
        filter(lambda x: x != [],
               map(lambda x: x[0] if city in x[1] else [], flight_destinations_dict.items())
               )
    )
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.