더 바람직 : 람다 함수 또는 중첩 함수 ( def
)?
정규 함수에 비해 람다를 사용하면 한 가지 이점이 있습니다. 식에서 생성된다는 것입니다.
몇 가지 단점이 있습니다.
- 이름 없음 (단지
'<lambda>'
)
- 독 스트링 없음
- 주석 없음
- 복잡한 진술 없음
또한 둘 다 동일한 유형의 객체입니다. 이러한 이유로 저는 일반적으로 def
람다 대신 키워드로 함수를 생성하는 것을 선호합니다 .
첫 번째 요점-동일한 유형의 객체입니다.
람다는 일반 함수와 동일한 유형의 객체를 생성합니다.
>>> l = lambda: 0
>>> type(l)
<class 'function'>
>>> def foo(): return 0
...
>>> type(foo)
<class 'function'>
>>> type(foo) is type(l)
True
람다는 함수이기 때문에 일류 객체입니다.
람다와 함수 :
- 인수로 전달할 수 있습니다 (일반 함수와 동일).
- 외부 함수 내에서 생성되면 해당 외부 함수의 지역에 대한 클로저가됩니다.
그러나 람다는 기본적으로 함수가 전체 함수 정의 구문을 통해 얻는 일부 항목이 누락되었습니다.
람바 __name__
는'<lambda>'
Lambda는 결국 익명의 함수이므로 자신의 이름을 모릅니다.
>>> l.__name__
'<lambda>'
>>> foo.__name__
'foo'
따라서 람다는 네임 스페이스에서 프로그래밍 방식으로 조회 할 수 없습니다.
이것은 특정 사항을 제한합니다. 예를 들어 foo
직렬화 된 코드로 검색 l
할 수 있지만 다음은 검색 할 수 없습니다.
>>> import pickle
>>> pickle.loads(pickle.dumps(l))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <function <lambda> at 0x7fbbc0464e18>:
attribute lookup <lambda> on __main__ failed
foo
자체 이름을 알고 있기 때문에 잘 조회 할 수 있습니다 .
>>> pickle.loads(pickle.dumps(foo))
<function foo at 0x7fbbbee79268>
Lambda에는 주석과 독 스트링이 없습니다.
기본적으로 람다는 문서화되어 있지 않습니다. foo
더 잘 문서화되도록 다시 작성해 보겠습니다 .
def foo() -> int:
"""a nullary function, returns 0 every time"""
return 0
이제 foo에는 문서가 있습니다.
>>> foo.__annotations__
{'return': <class 'int'>}
>>> help(foo)
Help on function foo in module __main__:
foo() -> int
a nullary function, returns 0 every time
반면, 람다에 동일한 정보를 제공하는 동일한 메커니즘이 없습니다.
>>> help(l)
Help on function <lambda> in module __main__:
<lambda> lambda (...)
그러나 우리는 그들을 해킹 할 수 있습니다 :
>>> l.__doc__ = 'nullary -> 0'
>>> l.__annotations__ = {'return': int}
>>> help(l)
Help on function <lambda> in module __main__:
<lambda> lambda ) -> in
nullary -> 0
그러나 도움말의 출력을 엉망으로 만드는 오류가있을 수 있습니다.
Lambda는 표현식 만 반환 할 수 있습니다.
Lambda는 복잡한 문을 반환 할 수없고 표현식 만 반환합니다.
>>> lambda: if True: 0
File "<stdin>", line 1
lambda: if True: 0
^
SyntaxError: invalid syntax
식은 분명히 다소 복잡 할 수 있으며 매우 열심히 시도 하면 람다로도 동일한 결과를 얻을 수 있지만 복잡성이 추가되면 명확한 코드를 작성하는 데 더 해가됩니다.
명확성과 유지 보수성을 위해 Python을 사용합니다. 람다를 과도하게 사용하면이를 막을 수 있습니다.
람다 의 유일한 장점 : 단일 표현식으로 생성 가능
이것이 가능한 유일한 장점입니다. 식으로 람다를 만들 수 있으므로 함수 호출 내에서 만들 수 있습니다.
함수 호출 내에서 함수를 생성하면 다른 곳에서 생성 된 이름에 비해 (비싸지 않은) 이름 조회를 피할 수 있습니다.
그러나 Python은 엄격하게 평가되기 때문에 이름 조회를 피하는 것 외에 다른 성능 향상은 없습니다.
매우 간단한 표현을 위해 람다를 선택할 수 있습니다.
나는 또한 대화 형 파이썬을 할 때 람다를 사용하여 여러 줄을 피하는 경향이 있습니다. 호출 할 때 생성자에 인수를 전달하려면 다음과 같은 코드 형식을 사용합니다 timeit.repeat
.
import timeit
def return_nullary_lambda(return_value=0):
return lambda: return_value
def return_nullary_function(return_value=0):
def nullary_fn():
return return_value
return nullary_fn
그리고 지금:
>>> min(timeit.repeat(lambda: return_nullary_lambda(1)))
0.24312214995734394
>>> min(timeit.repeat(lambda: return_nullary_function(1)))
0.24894469301216304
나는 위의 약간의 시간 차이가에서 이름 검색에 기인 할 수 있다고 믿는다 return_nullary_function
는 것을 참고 - 아주 무시할.
결론
Lambda는 특이점을 만들기 위해 코드 줄을 최소화하려는 비공식적 인 상황에 적합합니다.
Lambda는 나중에 올 코드 편집자에게 명확성이 필요한보다 공식적인 상황, 특히 중요하지 않은 경우에 적합하지 않습니다.
우리는 물체에 좋은 이름을 부여해야한다는 것을 알고 있습니다. 물체가 없을 때 어떻게 그렇게 할 수 있습니까? 이름 있습니까?
이러한 모든 이유로 저는 일반적으로 with def
대신에 함수를 만드는 것을 선호합니다 lambda
.
lambda
하지만, 난이 "매우 드문"이라고 동의, 그것은에 주요 기능에 대한 일반적인sorted
또는itertools.groupby
등, 예를 들면sorted(['a1', 'b0'], key= lambda x: int(x[1]))