본문 바로가기
개발/수학

lambda

by 로그인시러 2017. 2. 15.

- lambda calculus 에서 유래했다함. 

- 걍 익명함수.

- 코드의 가독성이 높아짐. (코드의 흐름이 끊기지 않고 자연스럽게 연결됨)

- 개인적으로 왜 lambda 함수는 multiline or multi statement 는 지원이 안되는지 궁금함 ..


  * multiline 관련 ..

  파이썬 만든 사람 답변

"But the complexity of any proposed solution for this puzzle is immense, to me: it requires the parser (or more precisely, the lexer) to be able to switch back and forth between indent-sensitive and indent-insensitive modes, keeping a stack of previous modes and indentation level. Technically that can all be solved (there's already a stack of indentation levels that could be generalized). But none of that takes away my gut feeling that it is all an elaborate Rube Goldberg contraption."

출처 : http://stackoverflow.com/questions/1233448/no-multiline-lambda-in-python-why-not


  * multi statement 관련 ..

There are several different answers I can give here, from your specific question to more general concerns. so from most specific to most general:

Q. Can you put multiple statements in a lambda?

A. No. But you don't actually need to use a lambda. You can put the statements in a def instead. ie:

def second_lowest(l):
    l.sort()
    return l[1]

map(second_lowest, lst)

Q. Can you get the second lowest item from a lambda by sorting the list?

A. Yes. As alex's answer poinst out, sorted() is a version of sort that creates a new list, rather than sorting in-place, and can be chained. Note that this is probably what you should be using - it's bad practice for your map to have side effects on the original list.

Q. How should I get the second lowest item from each list in a sequence of lists.

A. sorted(l)[1] is not actually the best way for this. It has O(N log(N)) complexity, while an O(n) solution exists. This can be found in the heapq module.

>>> import  heapq
>>> l = [5,2,6,8,3,5]
>>> heapq.nsmallest(l, 2)
[2, 3]

So just use:

map(lambda x: heapq.nsmallest(x,2)[1],  list_of_lists)

It's also usually considered clearer to use a list comprehension, which avoids the lambda altogether:

[heapq.nsmallest(x,2)[1] for x in list_of_lists]

출처 : http://stackoverflow.com/questions/862412/is-it-possible-to-have-multiple-statements-in-a-python-lambda-expression


이외에 lambda 관련 정리 잘 된 글 펌


오늘은 람다 형식과 그것을 이용하는 여러가지 함수들에 대해서 알아보겠습니다. 당장 완벽하게 소화하실 필요는 없을 것 같구요, 가벼운 마음으로 이런 것이 있다는 정도만 아셔도 되지 않을까 합니다. 람다 형식은 인공지능 분야나 AutoCAD라는 설계 프로그램에서 쓰이는 Lisp 언어에서 물려받았다고 하는데요, 함수를 딱 한 줄만으로 만들게 해주는 훌륭한 녀석입니다. 사용할 때는 아래와 같이 써주면 되지요.

lambda 인자 : 표현식

다음은 두 수를 더하는 함수입니다.

>>> def hap(x, y):
...   return x + y
...
>>> hap(10, 20)
30

이것을 람다 형식으로는 어떻게 표현할까요?

>>> (lambda x,y: x + y)(10, 20)
30

너무나 간단하죠? 함수가 이름조차도 없습니다. '그냥 10 + 20이라고 하면 돼지'라고 말씀하시면 미워잉~.

몇 가지 함수를 더 배워보면서 람다가 어떻게 이용되는지 알아보도록 하죠.

먼저 map 함수를 볼까요?

map(함수, 리스트)

이 함수는 함수와 리스트를 인자로 받습니다. 그렇죠? 그리고, 리스트로부터 원소를 하나씩 꺼내서 함수를 적용시킨 다음, 그 결과를 새로운 리스트에 담아준답니다. 말이 좀 복잡하죠? 그럴 때 예제를 보는 게 최고죠.

>>> map(lambda x: x ** 2, range(5))             # 파이썬 2
[0, 1, 4, 9, 16]  
>>> list(map(lambda x: x ** 2, range(5)))     # 파이썬 2 및 파이썬 3
[0, 1, 4, 9, 16]

위의 map 함수가 인자로 받은 함수는 lambda x: x ** 2구요, 리스트로는 range(5)를 받았습니다. range 함수는 알고계시죠? range(5) 라고 써주면 [0, 1, 2, 3, 4]라는 리스트를 돌려줍니다. 그리고 x ** 2 라는 것은 x 값을 제곱하라는 연산자죠.

map 함수는 리스트에서 원소를 하나씩 꺼내서 함수를 적용시킨 결과를 새로운 리스트에 담아주니까, 위의 예제는 0을 제곱하고, 1을 제곱하고, 2, 3, 4를 제곱한 것을 새로운 리스트에 넣어주는 것입니다.

위의 예제를 람다가 아닌 보통의 함수로 구현하면 어떻게 될까요?

이번엔 reduce 함수를 살펴봅시다.

reduce(함수, 순서형 자료)

형식은 위와 같구요, 순서형 자료(문자열, 리스트, 튜플)의 원소들을 누적적으로(?) 함수에 적용시킨답니다. 말이 진짜 어렵군요. 예제를 살펴보도록 하겠습니다.

>>> from functools import reduce   # 파이썬 3에서는 써주셔야 해요  
>>> reduce(lambda x, y: x + y, [0, 1, 2, 3, 4])
10

위의 예제는 먼저 0과 1을 더하고, 그 결과에 2를 더하고, 거기다가 3을 더하고, 또 4를 더한 값을 돌려줍니다. 한 마디로 전부 다 더하라는 겁니다. 생각보다 쉽죠?

하… 하… 하…

의기양양하게 '예'라고 대답하신 분들을 위해 짜증나는 예제를 권해드리죠~.

>>> reduce(lambda x, y: y + x, 'abcde')
'edcba'

전 원래 뭐 하나를 배우면 꼭 엽기적인 실험을 해본답니다. 더 짜증나라고 설명 안 해드릴랍니다~

그 다음은 filter를 살펴볼 차례입니다. 필터가 뭐죠? 정수기에서 물을 걸러주는 것이 필터죠? 에어컨의 바람 들어가는 곳에도 필터가 달려있구요.

filter(함수, 리스트)

파이썬의 필터는 이렇게 생겼는데요, 리스트에 들어있는 원소들을 함수에 적용시켜서 결과가 참인 값들로 새로운 리스트를 만들어줍니다. 다음은 0부터 9까지의 리스트 중에서 5보다 작은 것만 돌려주는 예제입니다.

>>> filter(lambda x: x < 5, range(10))       # 파이썬 2
[0, 1, 2, 3, 4]  
>>> list(filter(lambda x: x < 5, range(10))) # 파이썬 2 및 파이썬 3
[0, 1, 2, 3, 4]

lambda x: x<5 라고 쓰니까 왠지 수학책에서 본 듯한 느낌이 들지 않습니까? 수학자들이 파이썬을 좋아한다던데…

위의 예제가 어떻게 돌아가는지는 척 보면 아시겠죠?

0부터 9까지의 리스트에서 숫자를 하나씩 꺼냅니다.

그 숫자를 x라 하고, x < 5 가 '참'이면 살려줍니다.

살아남은 것들은 새로운 리스트에 넣어줍니다. 끝.

자, 이번엔 홀수만 돌려주는 filter를 만들어 보도록 합시다.

먼저 홀수가 뭔지 생각해볼까요?

짝수는 2로 나누어 떨어지는 수이고, 홀수는 2로 나누어 떨어지지 않는 수입니다.

짝수를 2로 나눈 나머지는 0이고, 홀수를 2로 나누면 나머지가 1이죠.

또, 나머지를 구할 땐 %라는 연산자를 쓰면 됩니다. 예를 들어서, 50을 8로 나누면 몫은 6이고 나머지는 2니까 50%8은 2가 되는 거지요.

이제 홀수를 돌려주는 필터를 만들어 보겠습니다.

>>> filter(lambda x: x % 2, range(10))        # 파이썬 2
[1, 3, 5, 7, 9]  
>>> list(filter(lambda x: x % 2, range(10)))  # 파이썬 2 및 파이썬 3
[1, 3, 5, 7, 9]

지난 시간에 '참'은 1이고 '거짓'은 0이라고 했죠? 위의 filter 함수를 실행시키면,

0을 2로 나눈 나머지는 0이니까 람다 함수의 결과값은 0이고, 0은 '거짓'이니까 버려집니다.

1을 2로 나눈 나머지는 1이니까 람다 함수의 결과값은 1이고, 1은 '참'이니까 통과하지요.

이런 식으로 수행하면서 홀수만 돌려주게 되는 거지요.

휴~ 이번 강좌는 설명하기 힘들어서 쓰면서 한참 애먹었네요. 잘 이해되지 않는 부분이 있으면 질문답변 게시판에 올려주세요. 그럼 안녕~


출처 : https://wikidocs.net/64

'개발 > 수학' 카테고리의 다른 글

고유값, 고유벡터  (0) 2017.01.11
라그랑주 승수법  (0) 2017.01.11

댓글