파이썬 람다는 왜 유용한가요? [닫은]


929

파이썬 람다를 알아 내려고합니다. 람다는 실제 생활에서 잊혀져 야하는 "흥미로운"언어 항목 중 하나입니까?

나는 그것이 필요할지도 모르는 몇 가지 엣지 사례가 있다고 확신하지만, 그 모호함을 감안할 때, 향후 릴리스 (다양한 정의를 기반으로 한 내 가정)에서 재정의 될 가능성과 코딩 선명도가 감소해야합니다. 피하십시오?

이것은 C 유형의 오버플로 (버퍼 오버플로)를 상기시킵니다-최상위 변수를 가리키고 다른 필드 값을 설정하기 위해 오버로드합니다. 마치 일종의 기술자 쇼맨쉽이지만 유지 보수 코더 악몽처럼 느껴집니다.


261
+1 좋은 질문-잘못된 가정 (람다의 모호함) =) 프로그래밍 기술을 판단하지 마십시오. 그것들을 평가하고 당신의 멘탈 툴킷에 추가하십시오. 마음에 들지 않으면 사용하지 말고 종교적으로되지 않고 논리적으로 토론 할 준비를하십시오.
Kieveli

41
하스켈 규칙! Lambda 함수는 표현력과 추상화 능력을 제공합니다.
Jonathan Barbero

11
@JAL LISP는 말할 것도없고 ...
ApproachingDarknessFish

8
@ApproachingDarknessFish "아, 그것은 당신의 아버지의 괄호입니다. 더 문명화 된 시대부터 더 문명화 된 무기입니다." - 오비 리스프 케노비
필드

답변:


1009

람다 함수 에 대해 이야기하고 있습니까? 처럼

lambda x: x**2 + 2*x - 5

그것들은 실제로 매우 유용합니다. Python은 함수를 다른 함수에 전달하여 작업을 수행 할 수있는 함수형 프로그래밍이라는 프로그래밍 스타일을 지원합니다 . 예:

mult3 = filter(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7, 8, 9])

로 설정 mult3합니다 [3, 6, 9]. 원래 목록에서 3의 배수 인 요소는 다음과 같습니다.

def filterfunc(x):
    return x % 3 == 0
mult3 = filter(filterfunc, [1, 2, 3, 4, 5, 6, 7, 8, 9])

물론,이 특정한 경우에, 당신은리스트 이해와 같은 것을 할 수 있습니다 :

mult3 = [x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9] if x % 3 == 0]

(또는로도 가능 range(3,10,3)하지만) 목록 이해력을 사용할 수 없으며 람다 함수가 무언가를 쓰는 가장 짧은 방법 일 수있는 더 정교한 다른 유스 케이스가 많이 있습니다.

  • 다른 함수에서 함수 반환

    >>> def transform(n):
    ...     return lambda x: x + n
    ...
    >>> f = transform(3)
    >>> f(4)
    7

    이것은 종종 파이썬 데코레이터와 같은 함수 래퍼를 만드는 데 사용됩니다.

  • 반복 가능한 시퀀스의 요소 결합 reduce()

    >>> reduce(lambda a, b: '{}, {}'.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])
    '1, 2, 3, 4, 5, 6, 7, 8, 9'
  • 대체 키를 기준으로 정렬

    >>> sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))
    [5, 4, 6, 3, 7, 2, 8, 1, 9]

나는 람다 함수를 정기적으로 사용합니다. 그들에게 익숙해지는 데 시간이 걸렸지 만 결국 나는 그들이 언어의 매우 귀중한 부분이라는 것을 이해하게되었습니다.


26
이해하기 쉬운 예제를 좋아하십시오. 그러나 감소 부분. 이 기능을 구현해야하는 경우 내가 할 것','.join(str(x) for x in [1,2,3,4,5,6,7,8,9])
etlds

3
BTW Python3에서 이것을 실행하면 실제 값을보기 위해 필터 결과에서 list를 호출해야하며 functools에서 reduce를 가져와야합니다.
Gerard

위의 "기능 프로그래밍"의 정의에 대해 확신합니까? 나에게는 약간 혼란 스러웠다.
stdout

3
핵심은 lambda함수가 익명이 될 수 있다는 것입니다 (모든 예에서와 같이). lambda어떤 것에 기능을 할당한다면, 당신은 그것을 잘못하고 def대신 사용해야 합니다.
Chris_Rands

1
@zgulser 정의가 아니라 함수형 프로그래밍으로 할 수있는 것에 대한 설명 일뿐입니다.
David Z

377

lambda그냥 멋진 표현 방법입니다 function. 그 이름 외에는 모호하거나 협박하거나 비밀이 없습니다. 다음과 같은 라인을 읽을 때, 교체 lambda에 의해 function당신의 마음에 :

>>> f = lambda x: x + 1
>>> f(3)
4

단지의 함수를 정의합니다 x. 와 같은 다른 언어는 다음과 같이 R명시 적으로 말합니다.

> f = function(x) { x + 1 }
> f(3)
4

알 겠어? 프로그래밍에서 가장 자연스러운 일 중 하나입니다.


36
이것은 프로그래밍이 아닌 배경 (예 : 정확한 과학)에서 온 사람들에게 훌륭한 설명입니다 lambda . 감사!
Gabriel

10
Raymond Hettinger는 자신의 대화 중 하나에서 그 이름을 애도했으며 'lambda'대신 'make function'이라는 이름으로 모든 혼란을 피할 수 있다고 말했다. :-)
ankush981

10
당신의 마음에 lambda의해 대체 하고 마지막 표현 전에 추가functionreturn
Ciprian Tomoiagă

4
@AaronMcMillin 사용해보십시오 type(lambda x: 3). lambda표현식과 def명령문은 모두 function객체를 생성 합니다. 생성 할 수 있는 인스턴스 lambda를 제한 하는 것은 식 의 구문 일뿐 입니다.
chepner

6
@AaronMcMillin 내 요점이 없습니다. 모든 함수를 a로 정의 할 수 없기 때문에lambda 발현을 a의 결과를 의미하지 않는다 lambda표현이 아닌 함수.
chepner

107

두 줄 요약 :

  1. 폐쇄 : 매우 유용합니다. 그들을 배우고, 사용하고, 사랑하십시오.
  2. 파이썬의 lambda키워드 : 불필요하고 때로는 유용합니다. 자신이 원격으로 복잡한 일을한다면, 그것을 버리고 실제 기능을 정의하십시오.

72

람다는 고차 함수를 다루는 매우 중요한 추상화 메커니즘의 일부입니다. 가치에 대한 올바른 이해를 위해 Abelson과 Sussman의 고품질 수업을 시청하십시오. SICP 책을 읽으십시오.

이것은 현대 소프트웨어 비즈니스에서 관련 문제이며 점점 인기를 얻고 있습니다.


1
람다 식은 C #과 같은 다른 언어에서도 인기를 얻고 있습니다. 그들은 아무데도 가지 않습니다. 클로저를 읽으면 Lambdas를 이해하는 데 유용한 연습이 될 것입니다. 클로저는 jQuery와 같은 프레임 워크에서 많은 코딩 마법을 가능하게합니다.
Dan Esparza

3
lambda와 일류 함수를 혼동하지 마십시오 . 파이썬은 극히 제한적인 lambda문장이지만 완전히 일류 함수입니다. 유일한 차이점은 전달하려는 함수의 이름을 지정해야한다는 것입니다.
Gareth Latty

59

람다는 GUI 프로그래밍에 매우 유용합니다. 예를 들어, 버튼 그룹을 만들고 있고 버튼 당 고유 한 콜백이 아닌 단일 매개 변수화 된 콜백을 사용하려고한다고 가정합니다. Lambda를 사용하면 쉽게 달성 할 수 있습니다.

for value in ["one","two","three"]:
    b = tk.Button(label=value, command=lambda arg=value: my_callback(arg))
    b.pack()

(참고 :이 질문은 특별히 질문하지만 functools.partiallambda사용 하여 동일한 유형의 결과를 얻을 수도 있습니다)

대안은 각 버튼마다 별도의 콜백을 생성하여 코드가 중복 될 수 있습니다.


1
이것이 정확히 내가 람다를 찾은 이유이지만, 왜 작동합니까, 함수를 똑바로 호출하는 것과 정확히 같습니다 ( stackoverflow.com/questions/3704568/… ). 늦었을 수도 있고 작동하지만 왜 작동합니까?
Rqomey

5
@Rqomey : 차이점은이 예제 value에서 루프로 정의 된다는 것입니다 . 다른 예에서 매개 변수는 항상 하나의 값만 가졌습니다. 과 같은 것을 추가 arg=value하면 현재 값이 콜백에 첨부됩니다. 이를 사용하지 않으면 콜백에서 변수에 대한 참조를 바인딩합니다. 루프가 이미 실행을 마치고 얼마 후에 콜백이 발생하기 때문에 참조에는 항상 변수의 최종 값이 포함됩니다.
Bryan Oakley

1
나는 어제 이것을 작동 시켰습니다. 솔직히 그것이 얼마나 유용한 지 믿을 수 없습니다 ... 루프 용 메뉴와 구성을위한 CSV 파일 중 하나에서 메뉴를 만들 수 있습니다. 정말 유용한 것들.
Rqomey

1
그것의 존재 functools.partial()는 당신이 덜 멍청이로 (없이 lambda) 이것을 할 수있게합니다 .
Gareth Latty

2
partial(my_callback, value)lambda arg=value: my_callback(arg)- 람다는 (다음 과제 인수 및 사용) 훨씬 더 cruft에이 있고는 의도가 무엇인지 덜 분명하다 (당신은 람다에서 미묘하게 다른 일을 할 수있다). 가져 오기는 실제로 문제가되지 않습니다 (어쨌든 파일이 있으며 파일 당 한 번입니다). 코드는 읽는 방법에 대해 가장 잘 판단되며 partial()람다보다 읽기가 훨씬 쉽습니다.
Gareth Latty

58

람다가 사라질지 의심 스럽다. 마침내 제거 시도 포기에 대한 Guido의 게시물을 참조하십시오 . 또한 충돌의 개요를 참조하십시오 .

Python의 기능적 기능에 대한 거래 내역에 대한 자세한 내용은이 게시물을 참조 하십시오 . http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

흥미롭게도, 람다 및 기타 기능적 특징의 도입에 동기를 부여한 맵, 필터 및 감소 기능은 목록 이해 및 생성기 표현으로 대체되었습니다. 실제로 reduce 함수는 Python 3.0의 내장 함수 목록에서 제거되었습니다. (단, 람다, 맵 또는 필터의 제거에 대한 불만을 제기 할 필요는 없습니다. :-)

내 자신의 두 센트 : 명확성이 나올 때까지는 그만한 가치가 거의 없습니다. 일반적으로 람다를 포함하지 않는 더 명확한 솔루션이 있습니다.


2
파이썬 3.0에서는 여전히 축소를 가져올 수 있습니다. 당신이 정말로 그것을 원한다면, 당신은 여전히 ​​그것을 가질 수 있습니다.
Paweł Polewicz

Guido의 시도는 구문에 대한 것이라 생각합니다. 이 사람은 또한 다음을 생각합니다 : cackhanded.com/blog/post/2008/01/24/…
leewz

38

파이썬에서 lambda함수를 인라인으로 정의하는 방법 일뿐입니다.

a = lambda x: x + 1
print a(1)

과..

def a(x): return x + 1
print a(1)

.. 정확 합니다.

람다로는 정규 함수로는 할 수없는 일이 없습니다. 파이썬 함수는 다른 것과 마찬가지로 객체이며 람다는 단순히 함수를 정의합니다.

>>> a = lambda x: x + 1
>>> type(a)
<type 'function'>

솔직히 말해서 lambda키워드는 파이썬에서 중복 이라고 생각합니다. 키워드를 사용할 필요가 없었습니다.

완전히 임의의 예를 들어, "Python의 람다는 깨졌습니다!" 기사에서 :

람다가 파손되는 방법을 확인하려면, 함수 목록 생성하려고 fs=[f0,...,f9]어디 fi(n)=i+n. 첫번째 시도:

>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13

나는 그것이 효과가 있었지만 끔찍하고 "비유 론적"이라고 주장한다.

>>> n = 4
>>> [i + n for i in range(10)]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

예, 동일하지는 않지만 목록에서 람다 함수 그룹을 생성 해야하는 원인을 본 적이 없습니다 . 다른 언어에서는 의미가 있지만 Python은 Haskell (또는 Lisp 또는 ...)이 아닙니다.

우리는 람다를 사용할 수 있으며 여전히 다음과 같은 방식으로 원하는 결과를 얻을 수 있습니다.

>>> fs = [(lambda n,i=i: i + n) for i in range(10)]
>>> fs[3](4)
7

편집하다:

람다가 유용한 몇 가지 경우가 있습니다. 예를 들어 다음과 같이 PyQt 애플리케이션에서 신호를 연결할 때 편리합니다.

w = PyQt4.QtGui.QLineEdit()
w.textChanged.connect(lambda event: dothing())

방금 추가 인수로 메소드를 w.textChanged.connect(dothing)호출 하면 오류가 발생합니다. 람다를 사용하면 랩핑 함수를 정의하지 않고도 인수를 깔끔하게 삭제할 수 있습니다.dothingevent


2
파이썬 변수 범위 지정 규칙이 그런 식으로 작동하기 때문에 "lambda is broken"인수가 손상됩니다. for-loop 안에 클로저를 만들면 같은 방식으로 물릴 것입니다.
Antti Haapala

1
람다는 다른 많은 언어 (예 : 자바 스크립트)와 같이 "익명"기능을 사용자에게 제공하는 파이썬의 방법입니다.
Stefan Gruenwald

1
a정의한 람다와 함수 가 정확히 동일 하지 않습니다 . :) 그들은 __name__적어도 분야별로 다릅니다 ...
nperson325681

1
인라인 함수 이상의 기능을 수행합니다.
kta

"다른 언어로 이해 될 수있다"는 당신의 주장은 이상합니다. 람다의 본질적인 특성이 있거나 그렇지 않습니다.
Titou

31

람다는 동일한 기능을 수행하지만 다른 상황에서는 유용한 기능 목록에 유용합니다.

Mozilla 복수 규칙 처럼 :

plural_rules = [
    lambda n: 'all',
    lambda n: 'singular' if n == 1 else 'plural',
    lambda n: 'singular' if 0 <= n <= 1 else 'plural',
    ...
]
# Call plural rule #1 with argument 4 to find out which sentence form to use.
plural_rule[1](4) # returns 'plural'

모든 사람들을 위해 함수를 정의해야한다면, 끝까지 화를 낼 것입니다.
또한, 같은 함수 이름과 좋지 않을까 plural_rule_1, plural_rule_2등 그리고 당신은 필요 거라고 eval()당신이 변수 기능 ID에 따라 때 그것.


1
이것은 F #에서 지금까지 본 패턴 일치 및 옵션과 관련된 간단한 조우와 유사합니다. 이 구문을 사용하는 방법에 대한 자세한 정보가 있습니까?
Ken

26

lambda명명 된 함수 나 목록 및 생성기 표현식을 사용하여 수행 할 수있는 거의 모든 작업을 수행 할 수 있습니다.

결과적으로 대부분의 경우 기본적으로 모든 상황에서 대화식 인터프리터로 작성된 스크래치 코드를 제외하고는 상황 중 하나에 불과합니다.


3
"대부분의 경우 기본적으로 어떤 상황이든 그 중 하나만해야합니다."기간. 통역사에 람다를 입력해도 도움이되지 않습니다.
S.Lott

11
@Javier 컨셉에 대한 "람다"에 대해 이야기하고 있다면 동의합니다. 그러나 우리가 파이썬 키워드 "lambda"에 대해 이야기한다면 : 1) 명명 된 함수는 더 빠르며 람다 (지도 + 필터)를 사용하는 거의 모든 곳에서 더 많은 명령문 (표현 + 표현)을 수행 할 수 있습니다. 표현식을 생성하거나 이해를 나열 할 수 있습니다 더 성능이 좋고 간결합니다. 일급 함수가 멋지지 않다는 것은 아닙니다. 단지 파이썬의 "lambda"키워드가 명명 된 함수를 사용하는 것만 큼 좋지 않다는 것입니다.
Aaron Maenpaa

3
람다는 sort = () 및 sorted ()의 key = 인수와 같은 콜백 인수를 취하는 함수와 함께 사용하는 데
Rick Copeland

19
@Rick 그것은 의심의 여지가 없지만, 실제로 "lambda"를보고 "zohmygod lambda"를 생각하고 파이썬에서 체계 코드를 작성하기 시작하면 파이썬의 람다 표현의 한계로 인해 실망 할 것입니다. 반면에, 자신에게 생각하기 시작하면 "목록 이해가 효과가 있을까요? 아니요. 명명 된 기능으로 혜택을받을 수 있습니까? 아니요. 괜찮습니다. 정렬 됨 (xs, 키 = 람다 x : x.name, x.height) ", 람다를 올바른 횟수만큼 사용하게됩니다.
Aaron Maenpaa

4
+1 : 람다를 사용할 때 이름없는 함수를 사용할 때는 충분히 강조 할 수 없습니다 . 그리고 이름에는 귀중한 지적 부가 가치가 있습니다.
Stephane Rolland

19

나는 몇 년 동안 파이썬을 사용해 왔으며 람다 가 필요한 경우를 본 적이 없습니다 . 실제로 튜토리얼 에서 알 수 있듯이 그것은 구문 설탕만을위한 것입니다.


8
그들은이다 매우 파이썬을 사용하여 GUI를 개발할 때 유용합니다. 종종 위젯에는 함수에 대한 참조가 필요합니다. 함수를 호출하고 인수를 전달하는 위젯이 필요한 경우 람다는 매우 편리한 방법입니다.
Bryan Oakley

1
함수에 여러 인수를 전달하는 것의 장점은 무엇입니까? func_name (a, b) : 람다를 사용하지 않고 a + b를 반환
dter

2
그것은 아니에요 필요 하지만, ESP, 많은 경우에 짧은 코드를 더 읽기를 작성하는 데 도움이됩니다. Java 또는 C ++와 같은 장황한 언어로
phuclv

17

파이썬의 람다 구현에 대해서는 말할 수 없지만 일반적으로 람다 함수는 정말 편리합니다. 그것들은 함수형 프로그래밍의 핵심 기술 (아마도 기술 일 수도 있음)이며 객체 지향 프로그램에서도 매우 유용합니다. 특정 유형의 문제의 경우 최상의 솔루션이므로 반드시 잊어서는 안됩니다!

클로저맵 함수 (파이썬 문서에 링크되어 있지만 함수 구조를 지원하는 거의 모든 언어로 존재 함) 를 읽고 왜 유용한 지 알아보십시오.


3
람다없이 그 일을 할 수 있습니다. 그것은 단지 큰 번거 로움입니다.
Brian

17

Lambda 함수 함수를 작성하는 관료적이지 않은 방법입니다.

그게 다야. 예를 들어 주 함수가 있고 값을 제곱해야한다고 가정 해 봅시다. 이것을하는 전통적인 방법과 람다 방법을 보자 :

전통적인 방법 :

def main():
...
...
y = square(some_number)
...
return something

def square(x):
    return x**2

람다 방식 :

def main():
...
square = lambda x: x**2
y = square(some_number)
return something

차이점을 보시겠습니까?

Lambda 함수는 목록 이해 또는 맵과 같은 목록과 잘 어울립니다. 사실, 목록 이해는 람다를 사용하여 자신을 표현하는 "파이 토닉"방식입니다. 전의:

>>>a = [1,2,3,4]
>>>[x**2 for x in a]
[1,4,9,16]

구문의 각 요소가 무엇을 의미하는지 봅시다 :

[] : "나에게 목록을 줘"

x ** 2 : "이 새로운 기능 사용"

x in a : "a의 각 요소에"

편리 해요? 이와 같은 기능 만들기. 람다를 사용하여 다시 작성해 보겠습니다.

>>> square = lambda x: x**2
>>> [square(s) for x in a]
[1,4,9,16]

이제 같은 언어이지만 더 중립적 인 map을 사용하겠습니다. 지도에는 두 가지 주장이 있습니다.

(i) 하나의 기능

(ii) 반복 가능

그리고 각 요소가 iterable의 각 요소에 적용되는 함수 인 목록을 제공합니다.

따라서 map을 사용하면 다음과 같은 결과를 얻을 수 있습니다.

>>> a = [1,2,3,4]
>>> squared_list = map(lambda x: x**2, a)

람다와 매핑을 마스터하면 데이터를 간결하게 조작 할 수 있습니다. Lambda 함수는 모호하지 않으며 코드 선명도를 제거하지 않습니다. 어려운 것과 새로운 것을 혼동하지 마십시오. 일단 사용을 시작하면 매우 분명합니다.


13

lambda내 생각 에 좋은 점 중 하나는 가치가 필요할 때까지 간단한 형식에 대한 평가를 연기하는 방법이라는 것입니다. 설명하겠습니다.

많은 라이브러리 루틴은 특정 매개 변수를 호출 할 수 있도록 구현됩니다 (람다 중 하나임). 아이디어는 실제 값이 사용될 때만 (가라 불릴 때) 계산됩니다. (고려 된) 예제는 요점을 설명하는 데 도움이 될 수 있습니다. 주어진 타임 스탬프를 기록 할 루틴이 있다고 가정하십시오. 루틴에서 현재 시간에서 30 분을 뺀 값을 사용하려고합니다. 당신은 그렇게 그렇게 부를 것입니다

log_timestamp(datetime.datetime.now() - datetime.timedelta(minutes = 30))

이제 실제 이벤트가 특정 이벤트가 발생하고 타임 스탬프가 그 시간에만 계산되기를 원할 때만 호출된다고 가정하십시오. 이렇게 할 수 있습니다

log_timestamp(lambda : datetime.datetime.now() - datetime.timedelta(minutes = 30))

log_timestamp이처럼 호출 가능 항목을 처리 할 수 있다고 가정하면 필요할 때이를 평가하여 해당 시간 소인을 얻습니다.

물론 operator모듈을 사용하여 이것을 수행하는 대체 방법이 있지만 요점을 전달했으면 좋겠습니다.

업데이트 : 여기 에 좀 더 구체적인 실제 예가 있습니다.

업데이트 2 : 이것이 썽크 라고 불리는 것의 예라고 생각합니다 .


11

위에서 언급했듯이 파이썬의 람다 연산자는 익명 함수를 정의하고 파이썬 함수는 클로저입니다. 클로저 개념을 연산자 람다와 혼동하지 않는 것이 중요합니다. 연산자 람다는 단지 구문상의 메타돈입니다.

몇 년 전에 파이썬으로 시작했을 때, 나는 람다를 많이 사용하여 목록 이해와 함께 멋지다고 생각했습니다. 그러나 나는 수천 점의 기능 포인트로 파이썬으로 작성된 큰 웹 사이트를 작성하고 유지해야합니다. 나는 경험을 통해 람다가 물건을 프로토 타입으로 만들 수는 있지만 몇 가지 키 저장을 저장하거나 때로는 그렇지 않은 경우를 제외하고 인라인 함수 (클로저라고 함)를 제공하지 않습니다.

기본적으로 이것은 몇 가지 요점으로 요약됩니다.

  • 의미있는 이름을 사용하여 명시 적으로 작성된 소프트웨어를보다 쉽게 ​​읽을 수 있습니다. 정의에 따른 익명 클로저는 이름이 없으므로 의미있는 이름을 가질 수 없습니다. 이 간결함은 어떤 이유로 람다 매개 변수도 감염시키는 것처럼 보이므로 람다 x와 같은 예를 종종 볼 수 있습니다. x + 1
  • 명명 된 클로저는 참조 할 이름이있을 때 이름으로 두 번 이상 참조 될 수 있으므로 명명 된 클로저를 재사용하는 것이 더 쉽습니다.
  • 이름이 트레이스 백과 오류 주위에 표시되므로 람다 대신 명명 된 클로저를 사용하는 코드를 디버깅하는 것이 더 쉽습니다.

그것들을 반올림하고 명명 된 클로저로 변환하는 충분한 이유입니다. 그러나 나는 익명의 폐쇄에 대해 다른 두 가지 원한을 가지고 있습니다.

첫 번째 원한은 단순히 언어를 어지럽히는 또 다른 불필요한 키워드라는 것입니다.

두 번째 원한은 더 깊고 패러다임 수준에 있습니다. 즉, 람다 미적분이 튜링이 아니기 때문에 메시지 전달, 객체 지향 또는 절차 스타일보다 유연성이 떨어지기 때문에 기능 프로그래밍 스타일을 홍보하는 것을 좋아하지 않습니다. 완료되었습니다 (행운 적으로 파이썬에서는 람다 내부에서도 이러한 제한을 벗어날 수 있습니다). 람다 가이 스타일을 홍보한다고 생각하는 이유는 다음과 같습니다.

  • 묵시적인 귀환이 있습니다. 즉, 그들은 '기능적'이어야합니다.

  • 그것들은 또 다른,보다 명백하고, 더 읽기 쉽고, 더 재사용 가능하며 더 일반적인 메커니즘 인 메소드에 대한 대안적인 상태 숨김 메커니즘입니다.

람다 프리 파이썬을 작성하려고 노력하고 람다를 제거합니다. 나는 파이썬이 람다가없는 약간 더 나은 언어라고 생각하지만 그것은 내 의견 일뿐입니다.


1
"... 파이썬 함수에서 클로저는"입니다. 내가 이해하는 것처럼 그것은 옳지 않습니다. 클로저는 함수이지만 함수는 항상 클로저가 아닙니다. 함수-> 람다 x, y : x + y. 클로저-> 람다 x : 람다 y : x + y
0atman

6
"람다 미적분이 튜링-완료가 아니기 때문에"는 명백한 잘못이며, 형식화되지 않은 람다 미적분은 튜링 완료입니다. 이것이 그토록 중요한 이유입니다. Y- 콤비 Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
네이터를

또한 튜링 완성도를 읽기 위해 위키 백과에 간다면 "클래식 예제는 람다 미적분학입니다."라고 말합니다.
Antti Haapala

진지하게-튜링 완료가 아님-이 답변은 진지하게 편집하거나 철회해야합니다.
Tony Suffolk 66

@ MarcinŁoś KISS를 준수하므로 투표권이 있습니다. 이에 비해 K & R 책은 과제를 부분적으로 또는 더 큰 표현으로 사용하는 것이 더 간결하지만 읽기 쉽지 않다고 언급합니다. 기능적 프로그래밍 패턴을 사용하는 경향은 트 라이트 (trite)와 진부한 (cliche)입니다. 사용 방법을 설명하는 것으로는 충분하지만, 유능한 개발자가되는 것이 가장 중요하다는 사실은 너무나 열악합니다. 완전히 주관적입니다. 이 주장은 클래스가없는 언어는 원시적이며 열등하며 부적절하다고 주장하는 C ++ 개발자와 유사합니다. "완전 완전성"이라는 논증은 현명하다.
typedeaf

11

람다는 실제로 함수형 프로그래밍의 아이디어에서 비롯된 매우 강력한 구조이며 가까운 장래에 파이썬을 쉽게 수정, 재정의 또는 제거하지 않는 것입니다. 그것들은 함수를 매개 변수로 전달할 수 있으므로보다 강력한 코드를 작성하는 데 도움이되므로 일급 시민으로서의 기능에 대한 아이디어를 얻을 수 있습니다.

람다는 혼동되는 경향이 있지만, 일단 이해가되면 다음과 같이 깔끔하고 우아한 코드를 작성할 수 있습니다.

squared = map(lambda x: x*x, [1, 2, 3, 4, 5])

위의 코드 줄은 목록에있는 숫자의 제곱 목록을 반환합니다. 물론 다음과 같이 할 수도 있습니다.

def square(x):
    return x*x

squared = map(square, [1, 2, 3, 4, 5])

앞의 코드가 더 짧다는 것은 명백하며, 한 곳에서만 맵 함수 (또는 함수를 매개 변수로 사용하는 유사한 함수)를 사용하려는 경우에 특히 그렇습니다. 이것은 또한 코드를보다 직관적이고 우아하게 만듭니다.

또한 @David Zaslavsky가 그의 답변에서 언급했듯이 목록 이해가 항상 애매 모호한 방법으로 가치를 얻어야하는 경우가 아닙니다.

좀 더 실용적인 관점에서, 최근 람다의 가장 큰 장점 중 하나는 GUI 및 이벤트 중심 프로그래밍이었습니다. Tkinter에서 콜백을 살펴보면 인수로 취하는 것은 모두 트리거 된 이벤트입니다. 예 :

def define_bindings(widget):
    widget.bind("<Button-1>", do-something-cool)

def do-something-cool(event):
    #Your code to execute on the event trigger

이제 몇 가지 주장을 전달하면 어떻게 될까요? 마우스 클릭의 좌표를 저장하기 위해 2 개의 인수를 전달하는 것만 큼 간단합니다. 다음과 같이 쉽게 할 수 있습니다.

def main():
    # define widgets and other imp stuff
    x, y = None, None
    widget.bind("<Button-1>", lambda event: do-something-cool(x, y))

def do-something-cool(event, x, y):
    x = event.x
    y = event.y
    #Do other cool stuff

이제 전역 변수를 사용 하여이 작업을 수행 할 수 있다고 주장 할 수는 있지만 특히 전역 변수가 특정 위치에서 사용되는 경우 메모리 관리 및 누출에 대해 걱정하고 있습니까? 프로그래밍 스타일이 좋지 않을 것입니다.

간단히 말해서, 람다는 훌륭하고 결코 과소 평가해서는 안됩니다. 파이썬 람다는 (더 강력한) LISP 람다와 같지 않지만, 실제로 많은 마법의 일을 할 수 있습니다.


감사. 나는 당신의 마지막 예를 완전히 이해하지 못했습니다. 어떻게 X를 올 Y 모두에 정의 maindo_something_cool? 무슨 일이 일어나는 xy기능에? 전달 된 값을 즉시 덮어 쓰는 것처럼 보입니까? 기능은 어떻게 알 수 event있습니까? 의견이나 설명을 추가해 주시겠습니까? 감사합니다
Sanjay Manohar

@SanjayManohar 나는 전달 x하고 y있으며 인수로 do-something-cool그리고 그 값이 함수에서 설정되어 람다를 사용하여 아무도 기대하지 않는 인수를 전달하는 방법을 보여줍니다. 이 widget.bind함수는 event해당 특정 위젯에서 GUI 이벤트를 식별 하는 매개 변수를 예상합니다 . 명확성을 높이려면 Tkinter의 프로그래밍 모델을 읽으십시오.
varagrawal

흠 나는 Tkinter 모델을 이해한다고 생각합니다. 그러나 아직도 확실히 이해하지 않는다 - 당신이 통과 x,y할 다음 x=event.x. 전달한 값을 덮어 쓰지 않습니까? 그리고 함수는 무엇인지 어떻게 알 수 event있습니까? 함수에 전달하는 위치를 알 수 없습니다. 아니면 방법입니까? 함수 이름에 빼기 기호도 허용됩니까?
Sanjay Manohar

@ SanjayManohar 친구 Tkinter와 Python에 대해 읽어야합니다. Tkinter는 이벤트 객체에 기본 액션으로 함수를 전달합니다. 에 관해서는 x, y, 이것은 단지 설명을위한 예일뿐입니다. 나는 Tkinter가 아니라 람다의 힘을 보여 주려고합니다. :)
varagrawal

1
이제 당신이 의도 한 것을 보았습니다. 함수를 받기 원 event하십니까? 이 경우 람다는 읽지 않아야 lambda event: do_something_cool(event,x,y)합니까?
Sanjay Manohar

8

Lambdas는 일반적으로 함수형 프로그래밍 스타일과 깊은 관련이 있습니다. 일부 데이터에 함수를 적용하고 결과를 병합하여 문제를 해결할 수 있다는 아이디어는 Google이 대부분의 알고리즘을 구현하는 데 사용하는 것입니다.

기능적 프로그래밍 스타일로 작성된 프로그램은 쉽게 병렬화되므로 최신 멀티 코어 머신에서 점점 더 중요 해지고 있습니다. 간단히 말해서, 당신은 그들을 잊지 않아야합니다.


7

람다를 알아 낸 것을 축하합니다. 제 생각에는 이것은 실제로 작동하는 강력한 구성입니다. 요즘 기능적 프로그래밍 언어로 향하는 추세는 피할 수 없으며 가까운 장래에 재정의되지도 않을 것입니다.

조금 다르게 생각하면됩니다. 곧 당신이 그것을 사랑합니다 확신합니다. 그러나 파이썬 만 다루는 경우주의하십시오. 람다는 실제 폐쇄가 아니기 때문에 어떻게 든 "파손"됩니다. 파이썬 람다는 고장났습니다 .


파이썬의 람다는 깨지지 않았습니다. 람다에서 지역 주민을 처리하는 두 가지 방법이 있습니다. 둘 다 장단점이 있습니다. 파이썬 (및 C #)이 취한 접근법은 아마도 순수 기능 언어에 익숙한 사람들에게는 반 직관적이라고 생각합니다. 순전히 기능적인 언어를 사용하면 그 접근법이 의미가 있다고 생각하지 않기 때문입니다.
Brian

실제로 반 직관적입니다. 나는 파이썬 프로그래머가 아니지만 삐걱 거리는 smalltalk에서는 동일하며 정기적 으로이 문제를 극복합니다. 그래서 나는 그것을 "깨진"것으로 간주합니다 :)
Norbert Hartl

아니요, 반투명 성과는 아무런 관련이 없습니다. 변수 이름의 어휘 범위는 함수의 어휘 범위 일뿐입니다. 루프는 어휘 범위를 도입하지 않습니다. 함수는 Javascript에서도 동일한 방식으로 작동합니다. var에 대한 범위가 필요한 경우 언제든지 수행 할 수 있습니다 (lambda scopedvar : lambda x : scopedvar + x) ()
Antti Haapala

6

방금 파이썬을 시작하고 Lambda로 먼저 뛰어 들었습니다.

이것은 아무것도 비난하지 않습니다. 누구나 쉽게 오지 않는 다른 것들을 가지고 있습니다.

람다는 실제 생활에서 잊혀져 야하는 '흥미로운'언어 항목 중 하나입니까?

아니.

필요한 경우가 있지만 일부 모호한 점이 있다고 확신합니다.

모호하지 않습니다. 내가 작업 한 지난 2 개의 팀은 모두이 기능을 항상 사용했습니다.

향후 릴리스에서 다시 정의 될 가능성 (다양한 정의를 기반으로 한 내 가정)

몇 년 전 클로저 의미를 수정하는 것 외에도 파이썬으로 재정의해야 할 심각한 제안은 없었습니다.

코딩 선명도가 감소합니다. 피해야합니까?

올바르게 사용한다면 명확하지 않습니다. 반대로, 더 많은 언어 구성이 가능 할수록 증가합니다 선명도가 .

이것은 C 유형의 오버플로 (버퍼 오버플로)를 상기시킵니다-최상위 변수를 가리키고 다른 필드 값을 설정하기 위해 오버로드합니다 ... 테크닉 쇼맨쉽이지만 유지 보수 코더 악몽.

람다는 버퍼 오버플로와 비슷합니까? 와. "유지 보수 악몽"이라고 생각하면 람다를 어떻게 사용하는지 상상할 수 없습니다.


5
나 (그리고 다른 사람들)가 전체 질문을 다시 읽게 한 -1. 다른 사람들은 그렇게하지 않고 대답 할 수있었습니다.
Paweł Polewicz

6

코드 중복을 피하기 위해 람다를 사용합니다. 그것은 쉽게 이해할 수있는 기능을 제공 할 것입니다. 예 :

def a_func()
  ...
  if some_conditon:
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)
  else
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)

나는 그것을 임시 람다로 바꾼다.

def a_func()
  ...
  call_big_f = lambda args_that_change: call_some_big_func(arg1, arg2, arg3, args_that_change)
  if some_conditon:
     ...
     call_big_f(argX)
  else
     ...
     call_big_f(argY)

5

오늘 데이비드 머츠의 책 '파이썬에서 텍스트 처리'를 읽기 시작했습니다. 그는 첫 장의 람다 예제에 대해 아주 간결하게 설명했지만 부록 A의 설명과 결합하여 나를 위해 (마지막으로) 페이지를 뛰어 넘었고 갑자기 그 가치를 이해했습니다. 그것은 그의 설명이 당신을 위해 효과가 있고 나는 여전히 발견 단계에 있다고 말하지 않기 때문에 나는 다음과 같은 것 외에는 이러한 반응에 추가하려고 시도하지 않을 것입니다 : 나는 파이썬에 익숙하지 않습니다. 이제 Mertz를 읽었으므로 나는 그것들을 얻었고 그것들이 프로그래밍에 대해 더 깔끔한 접근을 허용한다고 생각하는 것처럼 매우 유용하다고 생각합니다.

그는 단 한 줄 이 복잡한 것보다 낫다. 람다 (및 지난 주 목록 이해까지)가있는 비 OOP 프로그래머 독서 코드로서 나는 생각했습니다- 이것은 간단합니까? . 필자는 오늘 이러한 기능으로 인해 대체 코드보다 코드를 훨씬 더 읽기 쉽고 이해하기 쉽게 만들었습니다. 또한 재무 제표와 마찬가지로 Python은 초보자 사용자를 위해 설계된 것이 아니라 교육을 받으려는 사용자를 위해 설계되었습니다. 이 언어가 얼마나 강력한 지 믿을 수 없습니다. 그것이 람다의 목적과 가치에 (최종적으로) 시작되었을 때 나는 약 30 개의 프로그램을 찢어 내고 적절한 곳에 람다를 넣기를 시작했다.


5

람다를 사용하는 유용한 사례 는 긴 목록 이해의 가독성향상시키는 것입니다 . 이 예에서는 loop_dic명확성을 위해 짧지 만 loop_dic매우 길 다고 상상해보십시오 . i해당 값의 람다 버전 대신 포함 된 일반 값을 사용 하면을 얻을 수 있습니다 NameError.

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> loop_dic = lambda i: {"name": i["name"] + " Wallace" }
>>> new_lis = [loop_dic(i) for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

대신에

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> new_lis = [{"name": i["name"] + " Wallace"} for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

5

나는 실제로 람다가 심각하게 필요한 예를 줄 수 있습니다. 파일을 마우스 오른쪽 버튼으로 클릭하고 세 가지 옵션 중 하나를 할당하는 그래픽 프로그램을 만들고 있습니다. Tkinter (내가 작성하는 GUI 인터페이스 프로그램)에서 누군가 버튼을 누르면 인수를 취하는 명령에 할당 할 수 없다는 것이 밝혀졌습니다. 따라서 옵션 중 하나를 선택하고 선택한 결과를 원한다면 :

print 'hi there'

그럼 별거 아니야 그러나 특정 세부 사항을 갖기 위해 내 선택이 필요한 경우 어떻게해야합니까? 예를 들어, 선택 A를 선택하면 선택 A, B 또는 C에 종속되는 일부 인수를 취하는 함수를 호출합니다. TKinter는이를 지원할 수 없습니다. Lamda는 실제로 이것을 해결할 수있는 유일한 옵션이었습니다 ...


2
글쎄, 아마도 당신은 대신에 def foo...그다음에 통과 했을 수 있습니다 . 더 많은 코드이며 이름을 생각해 내야합니다. foolambda
Jon Coombs

4

주로 null 객체로 사용 하거나 매개 변수를 부분적으로 함수에 바인딩 하는 데 자주 사용합니다 .

예를 들면 다음과 같습니다.

null 객체 패턴을 구현하려면

{
    DATA_PACKET: self.handle_data_packets
    NET_PACKET: self.handle_hardware_packets
}.get(packet_type, lambda x : None)(payload)

매개 변수 바인딩의 경우 :

다음 API가 있다고 가정 해 봅시다.

def dump_hex(file, var)
    # some code
    pass

class X(object):
    #...
    def packet_received(data):
        # some kind of preprocessing
        self.callback(data)
    #...

그런 다음 수신 된 데이터를 파일로 빠르게 덤프하지 않으려면 다음과 같이하십시오.

dump_file = file('hex_dump.txt','w')
X.callback = lambda (x): dump_hex(dump_file, x)
...
dump_file.close()

4

나는 사용한다 lambda매개 변수가 포함 된 콜백을 만드는 데 합니다. 동일한 기능을 수행하는 메소드를 작성하는 것보다 한 줄에 람다를 작성하는 것이 더 깨끗합니다.

예를 들면 다음과 같습니다.

import imported.module

def func():
    return lambda: imported.module.method("foo", "bar")

반대로 :

import imported.module

def func():
    def cb():
        return imported.module.method("foo", "bar")
    return cb

4

저는 파이썬 초보자이므로 람다에 대한 명확한 아이디어를 얻으려면 'for'루프와 비교했습니다. 효율성 측면에서. 코드는 다음과 같습니다 (python 2.7).

import time
start = time.time() # Measure the time taken for execution

def first():
    squares = map(lambda x: x**2, range(10))
    # ^ Lambda
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0 seconds

def second():
    lst = []
    for i in range(10):
        lst.append(i**2)
    # ^ a 'for' loop
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0019998550415 seconds.

print abs(second() - first()) # Gives 0.0019998550415 seconds!(duh)

6
timeit일반적으로 time.time()값을 빼는 것보다 더 정확한 결과를 제공 하는 모듈에 관심이있을 수 있습니다 .
케빈

2
흠, first ()와 second ()의 시작에서 타이머를 다시 시작할 필요가 없습니까?
qneill

2

Lambda는 프로 시저 생성자입니다. 파이썬의 람다는 그다지 강력하지는 않지만 런타임에 프로그램을 합성 할 수 있습니다. 그런 종류의 프로그래밍을 이해하는 사람은 거의 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.