ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL. 28 람다 표현식(lambda) 사용하기
    TIL 2020. 11. 5. 18:23
    728x90

    ## lambda 표현식

    ## 람다 표현식은 식 형태로 되어 있어 람다 표현식이라 부르며,

    ## 함수를 간편하게 작성할 수 있어, "다른 함수의 인수"로 넣을때 자주 사용한다.


    ## 반화 값으로 매개변수 x + 10 형태의 함수를 람다 표현식으로 함수를 해보자

    1. def 

    def ppp(x):
        return x+10
    
    print(ppp(1))
    ::
    11

    2. 람다 표현식

    # 람다 표현식은 다음과 같이 lambda에 매개변수를 지정하고 :(콜론) 뒤에 반환값으로 사용할 식을 지정한다.

    # lambda 매개변수들: 식

    lambda x : x+10

    # 람다 표현식을 위와 같이 작성하면 함수 객체가 생성되는데, 이 상태만으로는 함수를 호출 할 수 없다.

    # 람다 표현식은 "이름없는"함수를 만들기 때문이다, 이때문에 람다 표현식을 익명 함수(anonymous function) 라고도 부른다.

    ## 람다로 만든 함수를 호출하기 위해선 임의의 변수에 할당하여 호출하면 된다.

    a = lambda x : x+10
    
    print(a(10))
    ::
    20

    ## 람다 표현식을 살펴보면 lambda x: x + 10은 매개변수 x 하나를 받고, x에 10을 더해서 반환한다는 뜻이다.

    # 즉, 매개변수, 연산자, 값 등을 조합한 식으로 반환값을 만드는 방식이다

    # 다음그림과 같이 def로 만든 함수와 비교해보자.


    ## 람다 표현식 자체로 호출하기

    ## 임의의 변수를 할당하지않고 ()로 묶어 람다 표현식 자체만으로도 함수를 호출 할 수 있는 방법이있다.

    ## (lambda 매개변수들: 식)(인수들) IDLE에서 좀 더 쉽게 확인가능

    (lambda x : x+10)(25) # (lambda 매개변수들: 식)(인수들)
    
    print((lambda x : x+10)(25))
    ::
    35

    ## 람다 표현식안에서는 변수를 만들 수 없다.

    (lambda x: y=10; x + y) # error

    ## 이처럼 y라는 변수를 람다 표현식에 만들 수 없다

    ## 따라서 반환값 부분은 변수 없이 식 1줄로 작성되어야 하며, 추가 변수가 필요할 경우 def 이용해야한다.


    ## 람다 표현식은 바깥에 있는 함수를 사용할 수 있다.

    y = 20
    
    (lambda x: x+y)(1)
    
    출력시
    ::
    21

     

    ## 위와 같이 매개변수 x 와 바깥의 변수 y 를 이용해 값을 반환 할 수 있다.


    ## 람다 표현식을 사용하는 이유

    ## 람다 표현식은 "함수의 인수 부분에서 함수를 간단하게 만들기 위해 사용한다" 대표적으로 map이다.

     

    def plus_ten(x):
        return x + 10
    
    b = list(map(plus_ten, [1, 2, 3])) ## map 객체로 저장되는 값을 사람이 보기 위해 list로 변환시켜주는 과정
    
    print(b)
    ::
    [11, 12, 13]

     

    ## map은 여러 개의 데이터를 한 번에 다른 형태로 변환하기 위해서 사용한다.

    # 따라서, 여러 개의 데이터를 담고 있는 list나 tuple을 대상으로 주로 사용하는 함수이다.

    ### 지금까지 map을 사용할 때 map(str, [1, 2, 3])와 같이 자료형 int, float, str 등을 넣었다

    ### 사실 plus_ten처럼 함수를 직접 만들어서 넣어도 된다.

    c = list(map(lambda x : x+10 ,[1, 2, 3])) 
    # 위 식의 b와 비교해보면 plus_ten 이라는 함수 자리를 람다 표현식으로 대체한 것
    
    print(c)
    ::
    [11, 12, 13]

     

    ## 위 식의 b와 비교해보면 plus_ten 이라는 함수 자리를 람다 표현식으로 대체한 것이며

    ## 대체할 경우 def 과정이 사라진 코드 단축효과를 볼 수 있다.

    ## 이처럼 "함수를 다른 함수의 인수로 넣을때" 편리하다


    ## 람다 표현식으로 매개변수가 없는 함수 만들기

    f = (lambda: 1)()
    print(f)
    ::
    1
    
    x = 10
    g = (lambda : x)()
    print(g)
    ::
    10

    ## 람다 표현식으로 매개변수가 없는 함수를 만들 때는 lambda 뒤에 아무것도 지정하지 않고 :(콜론)을 붙혀준다.

    ## 단, 콜론 뒤에는 반드시 반환할 값이 있어야 한다. 왜냐하면 표현식(expression)은 반드시 값으로 평가되어야 하기 때문이다.

    ## 람다 표현식에서 map, filter, reduce 사용하기

    ## 람다 표현식에서 조건문 사용하기

    # lambda 매개변수들: 식1 if 조건식 else 식2

    ## map을 이용해 a라는 리스트에서 3의 배수를 문자열로 출력

    <IDLE> # not vscode
    a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    list(map(lambda x : str(x) if x % 3 == 0 else x,a))
    :: 
    [1, 2, '3', 4, 5, '6', 7, 8, '9', 10]

    # map은 리스트의 요소를 각각 처리하므로 lambda 의 반환값도 요소여야 한다.

    ## 식 1 == str(x) , 조건식 == x % 3 == , 식2 == x


    ## 람다 표현식에서 조건문 사용시 주의할 점

    ## 1. if else 조건문 사용시 :(콜론)을 붙히지 않음 (일반적 조건문 문법과 다름)

    ## 2. 식1 if 조건식 else 식2 // 조건문이 참이면 식1, 거짓일때는 식2를 사용한다.

    ## 3. if를 사용했다면 반드시 else도 사용해줘야한다. (if만 사용시 error)

    ## 4. elif 를 사용 할 수 없다


    ## 람다 표현식에 조건문 여러개 사용하기

    # lambda 매개변수들: 식1 if 조건식1 else 식2 if 조건식2 else 식3

    # 리스트에서 1은 문자열로 변환하고, 2는 실수로 변환, 3 이상은 10을 더하는 식은 다음과 같이 작성

    <IDLE>
    list(map(lambda x : str(x) if x== 1 else float(x) if x==2 else x+10,a))
    ::
    ['1', 2.0, 13, 14, 15, 16, 17, 18, 19, 20]

     

    ## lambda 매개변수들: 식1 if 조건식1 else // 식2 if 조건식2 else 식3 ==>

    //를 기준으로 왼쪽 조건식 1개, 오른쪽 조건식 1개로 이해하면 편하다

    ## 위 식을 def로 바꿔 작성해보자

    def f(x):
        if x == 1:
            return str(x)
        elif x == 2:
            return float(x)
        else:
            return x+10
    
    a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    b = list(map(f,a))
    
    print(b)
    ::
    ['1', 2.0, 13, 14, 15, 16, 17, 18, 19, 20]
    

    ## 조건이 복잡하여 이해하거나 알아보기 힘들경우 억지로 람다 표현식을 사용하지 말고, def로 사용하는것을 권장한다.

    ## 복잡하고 어려운 코드는 작성 후 시간이 지나면 알아보기 어려운 경우가 많으니,

    코드는 길이가 조금 길어지더라도 알아보기 쉬워야 한다.(중요)


    ## mpa에 객채 여러개 넣기

    <IDLE>
    a = [1, 2, 3, 4, 5]
    b = [2, 4, 6, 8, 10]
    
    list(map(lambda x, y: x * y, a, b))
    ::
    [2, 8, 18, 32, 50]

    ## map은 리스트 등의 반복 가능한 객체를 여러개 넣을 수 있다.

    ## 위 코드는 두 리스트의 요소를 서로 곱해 새로운 리스트를 만드는 방법이다.

    ## 리스트 2개를 처리해야하는 경우 lambda x, y : x*y 처럼 매개변수를 2개 지정해주면 된다.

    ## 그다음 리스트 2개를 ,(콤마)로 구분해 넣어주면 된다.

    ## 즉, 람다 표현식의 매개변수 개수에 맞춰 반복 가능한 객체를 콤마로 구분하여 넣어주면 된다.

    ## 여기서 반복 가능한 객체는 a, b 이며, a, b 의 요소의 개수가 다를 경우 요소의 개수가 더 작은 객체를 기준으로 출력해준다

    ## ex : a = [1, 2] ==> 해당 식의 반환 값은 [2, 8] 까지만 반환

    ## ex : a = [1, 2, 3, 4, 5, 6, 7, 8] ==> 해당 식의 반환 값은 [2, 4, 6, 8, 10] 까지만 반환 (b의 요소 개수 5개)

     


    ## filter 사용하기

    # filter는 반복 가능한 객체에서 특정 조건에 맞는 요소만 가져오는데,

    # filter에 지정한 함수의 반환값이 True일 때만 해당 요소를 가져온다.

    # filter(함수, 반복가능한객체)

    ## def를 이용한 리스트에서 5보다 크면서 10보다 작은 숫자를 가져오기.

    a = [8, 3, 2, 10, 15, 7, 1, 9, 0, 11]
    
    def aaa(x):
        return x > 5 and x <10
    
    print(list(filter(aaa, a)))
    ::
    [8, 7, 9]

    ## 람다 표현식을 이용한 리스트에서 5보다 크면서 10보다 작은 숫자를 가져오기.

    a = [8, 3, 2, 10, 15, 7, 1, 9, 0, 11]
    
    b = list(filter(lambda x : x > 5 and x < 10, a))
    
    print(b)
    ::
    [8, 7, 9]
    
    

    ## 즉 filter 는 x > 5 and x <10 조건 중 참인 것만을 가져오고, 거짓은 버림


    ## reduce 사용하기

    # reduce는 반복 가능한 객체의 각 요소를 지정된 함수로 처리한 뒤 이전 결과와 누적해서 반환하는 함수

    # (reduce는 파이썬 3부터 내장 함수가 아닙니다. 따라서 functools 모듈에서 reduce 함수를 가져와야 한다)

    # from functools import reduce

    # reduce(함수, 반복가능한객체)

    ## def로 reduce 사용하기

    from functools import reduce
    
    a = [1, 2, 3, 4, 5]
    
    def bbb (x, y):
        return x+y
    
    print(reduce(bbb, a))
    ::
    15

    ## 함수 bbb에서 x + y를 반환하도록 만들었으므로 reduce는 그림과 같이 요소 두 개를 계속 더하면서 결과를 누적한다

    ## 람다 표현식으로 reduce 사용하기

    a = [1, 2, 3, 4, 5]
    
    from functools import reduce
    
    c = reduce(lambda x, y : x+y, a)
    
    print(c)
    ::
    15

     


    # 참고 | map, filter, reduce와 리스트 표현식

    ## 리스트(딕셔너리, 세트) 표현식으로 처리할 수 있는 경우에는 map, filter와 람다 표현식 대신 리스트 표현식을 사용하는 것이 좋습니다. list(filter(lambda x: x > 5 and x < 10, a))는 다음과 같이 리스트 표현식으로도 만들 수 있습니다.

    <IDLE>
    a = [8, 3, 2, 10, 15, 7, 1, 9, 0, 11]
    
    [i for i in a if i > 5 and i < 10]
    ::
    [8, 7, 9]
    
    

    ### 리스트 표현식이 좀 더 알아보기 쉽고 속도도 더 빠릅니다.

     

    ## 또한, for, while 반복문으로 처리할 수 있는 경우에도 reduce 대신 for, while을 사용하는 것이 좋다.

    왜냐하면 reduce는 코드가 조금만 복잡해져도 의미하는 바를 한 눈에 알아보기가 힘들다.

    이러한 이유로 파이썬 3부터는 reduce가 내장 함수에서 제외되었다.

     

    # reduce(lambda x, y: x + y, a)는 다음과 같이 for 반복문으로 표현할 수 있습니다.

    <IDLE>
    a = [1, 2, 3, 4, 5]
    
    x = a[0]
    
    for i in range(len(a) - 1):
    
    ... x = x + a[i + 1]
    
    ...
    
    x
    ::
    15
    
    

    728x90
Designed by Tistory.