본문 바로가기

Python

4.7. lambda 함수 사용하기

파이썬은 한 줄짜리 미니-함수를 바로바로 정의할 수 있는 흥미로운 구문을 지원합니다. Lisp에서 빌려온 이른바 이 lambda 함수는 함수가 요구되는 곳이면 어디든지 사용할 수 있습니다. 
 
예제 4.20.  람다(lambda) 함수 

 

  1. >>> def f(x):
  2. ...     return x*2
    ...     
    >>> f(3)
    6
    >>> g = lambda x: x*2  ①
    >>> g(3)
    6
    >>> (lambda x: x*2)(3) ②
    6

 

①  이는 람다(lambda) 함수로서 위의 정상 함수와 똑 같은 일을 합니다. 여기에서 생략된 구문에 주목하세요: 인자 리스트 주위에 반괄호가 없으며, return 키워드가 없습니다 (전체 함수가 오직 표현식만 가능하므로, 묵시적으로 반환됩니다). 또한, 함수에 이름도 없습니다. 그러나 자신에게 할당된 변수를 통하여 호출될 수 있습니다.  
②  변수에 할당하지 않아도 람다(lambda) 함수를 사용할 수 있습니다. 이것이 세상에서 제일 유용한 것은 아니겠지만, 람다가 그저 한 줄짜리 함수라는 사실 만큼은 확실하게 보여줍니다.  
 
일반적으로 말해 람다(lambda) 함수는 (선택적 인자를 포함하여) 인자를 얼마든지 취해 단일한 표현식의 값을 돌려주는 함수입니다. 람다(lambda) 함수는 명령어를 포함할 수 없습니다. 그리고 하나 이상의 표현식을 담을 수 없습니다. 람다(lambda) 함수 안에 너무 많은 것을 구겨 넣으려 하지 마세요; 좀 더 복잡한 식이 필요하면 대신에 보통의 함수를 정의하고 원하는 만큼 만드세요. 
 
☞ 람다(lambda) 함수는 스타일의 문제입니다. 반드시 람다 함수를 사용할 필요는 없습니다; 어디든지 람다 함수를 사용할 수 있는 곳이라면 따로 정상 함수를 정의해서 대신에 그 함수를 사용해도 좋습니다. 본인은 재사용이 필요없는 특정한 코드를 캡슐화해 넣고 싶은 경우에 람다 함수를 사용합니다. 수 많은 한 줄짜리 함수로 코드를 어지럽히고 싶지 않기 때문입니다.  
 
 
4.7.1. 실-세계의 람다(lambda) 함수 
다음은 apihelper.py에 있는 람다(lambda) 함수입니다: 

 

  1.     processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
 
여기에서 단순한 형태의 and-or 트릭을 사용하고 있음에 주목하세요. 지금은 문제가 없습니다. 왜냐하면 람다(lambda) 함수는 불리언 문맥에서 언제나 참이기 때문입니다. (그렇다고 해서 람다(lambda) 함수가 거짓 값을 돌려주지 못한다는 뜻은 아닙니다. 이 함수는 언제나 참입니다; 무엇이든 그의 반환 값이 될 수 있습니다.) 
 
또 주목할 것은 아무 인자 없이 split 함수를 사용하고 있다는 것입니다. 이미 문자열 가르기에서 사용된 것을 보신 바 있습니다. 그러나 인자가 없으면 공백문자를 기준으로 가릅니다. 
 
예제 4.21. 인자 없이 사용하는 split 함수 

 

  1. >>> s = "this   is\na\ttest"  ①
  2. >>> print s
    this   is
    a test
    >>> print s.split()           ②
    ['this', 'is', 'a', 'test']
    >>> print " ".join(s.split()) ③
    'this is a test'

 

①  이는 여러줄 문자열로서, 삼중 따옴표 대신에 피신 문자로 정의되어 있습니다. \n는 줄바꿈 문자이며, \t는 탭 문자입니다.  
②  인자없이 split 함수를 호출하면 공백문자를 기준으로 가릅니다. 그래서 세 개의 공백 문자와 줄바꿈 문자 그리고 탭 문자는 모두 같습니다.  
③  split로 문자열을 가르고 난 다음 공간 문자 한개를 가름자로 사용하여 join으로 다시 결합하면 공백문자를 표준화할 수 있습니다. 이것이 바로 info 함수가 하는 일로서 여러줄 문서화 문자열(doc string)을 한줄로 축약합니다.  
 
그래서 info 함수는 이 lambda 함수와 split 함수 그리고 and-or 트릭으로 실제로 무슨 일을 하는가?     

 

  1. processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
 
processFunc는 이제 함수이지만, 그것이 어느 함수인가는 collapse 변수의 값에 따라 다릅니다. collapse가 참이면 processFunc(string)은 공백으로 축약됩니다; 그렇지 않으면 processFunc(string)는 그의 인자를 그대로 돌려줍니다. 
 
비주얼 베이직(Visual Basic) 같이 유약한 언어에서 이렇게 하려면 아마도 문자열과 collapse 인자를 받고 if 서술문을 사용하여 공백문자로 축약할지 말지를 결정한 다음, 적절한 값을 돌려주는 함수를 만들어야 합니다. 이는 가능한 모든 사례마다 일일이 함수가 처리해야 하기 때문에 비효율적입니다. 호출할 때마다, 여러분이 원하는 것을 돌려주기 전에 공백을 축약해야 할지 말지를 결정할 필요가 있습니다. 파이썬에서는 함수로부터 결정 로직을 분리할 수 있으며 정확하게 (오직) 원하는 것을 돌려주도록 맞춤-재단된 람다(lambda) 함수를 정의할 수 있습니다. 이 방법이 더 효율적이며 더 우아하고 그리고 성가신 에러가 더 적습니다.