ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] lambda, map
    언어/파이썬 & 장고 2018. 7. 12. 23:20

    lambda, map, filter 같은 경우는 사실 가독성 부분에서 좋지 않다는 생각이 들어 지양하고 있었는데 장점이 있어서 정리해 봅니다.

    lambda(람다) 함수

    lambda (이후 '람다'라고 호칭)함수는 익명함수로 메모리를 절약하는 이점이 있습니다. 또한 가독성을 향상시킨다 라고도 나오지만 함수와 비교했을 때 가독성이 좋은건지는 잘 모르겠습니다. (개인적인 의견)

    일반적인 함수는 객체를 만들고, 재사용을 위해 함수 이름(메모리)를 할당을 합니다.

    # lambda 인수1, 인수2, ... : 인수를 이용한 표현식
    sum = lambda a, b: a+b
    result = sum(3,4)
    print(result)
    # 7

    왜 사용할까?

    익명함수이기 때문에 한번 쓰이고 다음줄로 넘어가면 힙(heap) 메모리 영역에서 증발하게 됩니다. (단발성으로 사용하게 될 때 유용)

    자세하게 설명하자면 파이썬에서 모든 것이 객체로 관리되고 각 객체는 레퍼런스 카운터를 갖게 되는데 해당 카운터가 0 - 어떤 것도 참조를 하지 않게 되면 메모리를 환원하게 됩니다. - 이러한 역할을 하는 것이 가비지 컬렉터입니다.

    모든 람다 함수가 사용 후 메모리에서 증발할까?

    위의 예시와 같은 경우는 람다함수(객체)를 sum이라는 변수에 저장합니다. 위의 설명대로라면 sum()를 사용 후 다음 줄에서 삭제가 되어야 하지만 실제로는 삭제되지 않습니다. sum이라는 변수의 메모리에 람다함수의 메모리가 저장되어 있어있기 때문입니다. 람다함수가 사용 후 메모리에서 증발하기 위해선 함수의 인자값에 전달 되었을 때 증발하게 됩니다. 또 함수 내부에서 사용하는 람다일 경우 해당 함수가 종료되는 순간 메모리에서 증발합니다.

    map 함수

    내장함수이며 입력받은 자료형의 각 요소가 함수에 의해 수행된 결과를 묶어서 map iterator 객체로 반환합니다. map함수는 게으른 연산을 진행해서 메모리를 크게 절약할 수 있습니다. 게으른 연산을 진행하기 때문에 값을 한번 사용하면 사용했던 값은 다시 호출할 수가 없습니다.

    # map(function, iterable)
    # 예시
    li = [1, 2, 3]
    result = list(map(lambda i: i ** 2 , li))
    print(result)
    print(result)
    
    
    # [1, 4, 9]
    # result

    게으른 연산(lazy evaluation)이란?

    필요할 때만 가져다 사용합니다. 보통 iterator 객체들이 게으른 함수입니다. (아닐 수도 있음 )

    iterator 객체

    • next() 메소드로 데이터를 순차적으로 호출 가능
    • 마지막 데이터 이후 next()를 호출하면 StopIteration 에러 발생
    • for 문을 사용할 때, 파이썬 내부에서는 임시로 list를 iterator로 변환해서 사용

    iterator 예시

    map()

    li = [1, 2, 3]
    result = map(lambda i: i * i, li)
    
    print(type(result))
    
    
    print(next(result))
    print(next(result))
    print(next(result))
    
    # next(result) # StopIteration 발생
    
    
    # 결과
    # <class 'map'>
    # 1
    # 4
    # 9

    iter()

    li = [1, 2, 3]
    result = iter(li)
    
    print(type(result))
    
    print(next(result))
    print(next(result))
    print(next(result))
    # next(result) # StopIteration 발생
    
    
    
    # 결과
    # <class 'list_iterator'>
    # 1
    # 2
    # 3

    generator expression

    li = [1, 2, 3]
    result = (val*val for val in li)
    
    print(type(result))
    
    print(next(result))
    print(next(result))
    print(next(result))
    # next(result) # StopIteration 발생
    
    
    # 결과
    # <class 'generator'>
    # 1
    # 4
    # 9


    댓글