[TIL - 9 / Python] lambda 표현식

haejun-kim·2020년 7월 24일
1

[Python]

목록 보기
16/19
post-thumbnail

람다 표현식

현재까지는 def로 함수를 정의해서 사용했으면 이번에는 람다 표현식으로 익명의 함수를 만드는 방법을 알아보자. 람다 표현식은 식 형태로 되어있다고 해서 람다 표현식(lambda expression)이라고 부른다. 특히, 람다 표현식은 함수를 간편하게 작성할 수 있어서 다른 함수의 인수로 넣을 때 주로 사용한다.

def 함수명()

  • 함수의 이름이 있다.
  • 함수 내부에서 처리하는 로직들을 문장으로 작성하는 블록으로 구성

lambda 표현식

  • 함수의 이름이 없다.
  • 인라인 형식의 간단한 표현식만 올 수 있다.
  • return없이 표현식의 결과가 리턴된다.

람다 표현식의 사용

그래서 람다 표현식을 어떻게 사용하는데? 우리에게 아직은 친숙하지 않은 람다 표현식을 바로 이해하려 하기보다는 그나마 조금은 더 익숙한 함수를 작성해보고 그 함수를 람다 표현식으로 바꾸는 연습을 하며 이해해보자.

다음의 plus_ten함수는 숫자를 받은 뒤 10을 더한 값을 반환해주는 함수이다.

def plus_ten(x):
    return x + 10
    
print(plus_ten(1)) # 11

이 함수를 람다 표현식으로 바꿔보자

  • lambda에 매개변수를 지정한다.
  • 콜론(:) 뒤에 반환값으로 사용할 식을 지정한다.
print(lambda x : x + 10)

실행결과 <function <lambda> at 0x7faa3adb9160>
실행해보면 함수 객체가 나오고, 원했던 결괏값은 나오지 않는다. 왜냐하면 람다 표현식은 이름이 없는 함수(익명 함수)를 생성하기 때문이다. 그래서 람다로 만든 익명 함수를 호출하기 위해서는 생성한 람다 표현식을 변수에 할당하고 해당 변수를 호출하면 된다.

plus_ten = lambda x : x + 10
print(plus_ten(1)) # 11

위의 람다 표현식을 해석하면 매개변수 x를 하나 받고, x10을 더해서 반환한다는 뜻으로 해석할 수 있다.

람다 표현식 자체 호출

위의 내용을 공부하니 이런 의문이 들었다.

람다 표현식을 호출하기 위해서는 매번 새로운 변수에 할당해야할까? 람다 표현식을 사용하는 이유 중 하나는 다른 함수와의 이름에서 충돌을 막기 위한 이유도 있는데, 이렇게되면 변수의 이름이 충돌이 일어날 가능성이 생기지 않을까?

그리고 어렵지 않게 해답을 찾을 수 있었다. 프로그래밍 언어를 만드신 분들은 역시 내가 생각한 부분은 모두 생각하셨다. 람다 표현식 자체를 호출하는 방법이 있었다. 다음과 같이 표현하면 자체 호출이 가능하다.

print((lambda x : x + 10)(1))

람다 표현식을 ()로 묶고, 뒤에 다시 ()를 붙이고 인수를 넣어서 호출하면 된다.

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

람다 표현식에서 주의할 점은 람다 표현식 안에서는 새 변수를 만들 수 없다. 따라서 반환값 부분은 변수 없이 식 한줄로 표현할 수 있어야 한다. 변수가 필요한 경우에는 def로 함수를 작성하자.

>>> (lambda x: y = 10; x + y)(1)
SyntaxError: invalid syntax

단, 람다 표현식 바깥에 있는 변수는 사용할 수 있다.

>>> y = 10
>>> (lambda x: x + y)(1)
11

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

람다 표현식은 매개변수가 없는 함수를 만들때는 lambda 뒤에 아무것도 지정하지 않고 :을 붙인다. 단, 콜론 뒤에는 반환할 값이 있어야 한다. 왜냐하면 표현식은 반드시 값으로 평가되어야 하기 때문이다.

>>> (lambda : 1)()
1
>>> x = 10
>>> (lambda : x)()
10

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

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

람다 포현식 안에서 조건부 표현식 if, else를 사용할 때는 :을 붙이지 않는다. 조건부 표현식은 식1 if 조건식 else 식2와 같이 사용하며,
식1: 조건식이 참일 때 사용할 식 표현
식2: 조건식이 거짓을 때 사용할 식 표현
이렇게 표현하면 된다. 특히 람다 표현식에서 if를 사용했다면 반드시 else를 사용해야한다. 그렇지 않으면 문법 에러가 발생하기 때문에 주의하자.
그리고 람다 표현식 안에서는 elif를 사용할 수 없다. 그렇기 때문에 여러가지의 조건 표현은 식1 if 조건식1 else 식2 if 조건식2 else 식3 과 같이 if를 연속적으로 사용해야한다.


Assignment

Q1)

다음 코드를 실행해보고 print문으로 출력되는 출력결과를 확인해보고 types 모듈에 LambdaType외에도 어떤 타입들이 있는지 조사해보자.

import types

f = lambda x,y,z : x+y+z

print(f)
print(type(f))
print(type(f) == types.LambdaType)
  • 실행 결과

출력되는 결과를 확인해보자. 먼저 람다 표현식으로 작성한 f라는 함수 자체를 출력해보니 lambda function이라는 것을 알 수 있다. 또한 이 ftype을 출력해보니 function이라는것도 확인할 수 있다.
마지막 print가 True가 출력된 것을 보니 types 모듈에 LambdaType이 존재한다는것을 유추해볼 수 있다.

그럼 추가적으로 types라는 모듈에 LamdaType외에는 어떤것들이 존재할지 확인해보자.

print(dir(types))
  • 실행 결과

위와 결과를 확인해보면 어떤 타입들이 존재하는지 확인할 수 있다. 물론 저 안에 LambdaType도 존재한다!

Q2)

다음과 같이 비밀번호의 길이와 대문자가 포함된것을 확인하는 간단한 함수가 있습니다.

def check_password(password):
    if len(password) < 8:
        return 'SHORT_PASSWORD'

    if not any(c.isupper() for c in password):
        return 'NO_CAPITAL_LETTER_PASSWORD'

    return True

이함수에 있는 if문 두개를 람다표현식을 이용하여 다음과 같은 형식으로 작성해 보세요.
lambdas 리스트안에 두개의 람다표현식을 작성해야하며 주석으로 표시된 프린트가 출력결과로 나와야 합니다.

lambdas = [ 

]

def check_password_using_lambda(password):

    for f in lambdas:
        if f(password) is not None:
            return f(password)

    return True


print( check_password_using_lambda('123') )            # SHORT_PASSWORD
print( check_password_using_lambda('12356789f') )      # NO_CAPITAL_LETTER_PASSWORD
print( check_password_using_lambda('123456789fF') )    # True
  • 풀이 코드
lambdas = [ 
lambda password : "SHORT_PASSWORD" if len(password) < 8 else "NO_CAPITAL_LETTER_PASSWORD" if not any(c.isupper() for c in password) else True
]

def check_password_using_lambda(password):

    for f in lambdas:
        if f(password) is not None: 
            return f(password)

    return True


print( check_password_using_lambda('123') )            # SHORT_PASSWORD
print( check_password_using_lambda('12356789f') )      # NO_CAPITAL_LETTER_PASSWORD
print( check_password_using_lambda('123456789fF') )    # True

람다 표현식에서 조건문을 사용하려면 다음을 기억하면 된다.
lambda 매개변수들 : 표현식1 if 조건식 else 표현식2 if 조건식 else 표현식3
따라서 첫번째 조건에 대한 식으로 만약 password 길이가 8보다 작으면 SHORT_PASSWORD 를 출력해주고 그게 아니라 password에 대문자가 하나도 없으면 NO_CAPITAL_LETTER_PASSWORD를 출력 두가지 조건 다 만족하지 않으면 True를 return해라. 라는 의미로 위와 같이 작성해주었다.

코드 실행 결과는 다음과 같다.

  • 실행 결과

0개의 댓글