부분 적용이 멋지다. functools.partial
람다를 통과 할 수없는 기능은 무엇입니까 ?
>>> sum = lambda x, y : x + y
>>> sum(1, 2)
3
>>> incr = lambda y : sum(1, y)
>>> incr(2)
3
>>> def sum2(x, y):
return x + y
>>> incr2 = functools.partial(sum2, 1)
>>> incr2(4)
5
가 functools
보다 효율적으로, 또는 읽을 어떻게 든?
답변
functools.partial
람다를 통과 할 수없는 기능은 무엇입니까 ?
추가 기능 측면에서는 그리 많지 않지만 (나중에 참조하십시오) – 가독성은 보는 사람의 눈에 있습니다.
함수형 프로그래밍 언어 (특히 리스프 / 계획 가족의 것)을 잘 알고있는 대부분의 사람들은 좋아 보인다 lambda
잘 – 나는 “가장”, 확실히 말을 하지 모두 귀도 내가 확실히 ( “익숙”그 사이에 있기 때문에 등 ) 아직 lambda
파이썬에서 눈에 띄지 않는 이상으로 생각합니다 …
그는 파이썬으로 그것을 받아 들인 것에 대해 회개했지만 “파이썬의 결함”중 하나로 파이썬 3에서 제거하려고 계획했습니다.
나는 그를 완전히지지했다. (I 사랑 lambda
제도에 … 잠시 한계를 파이썬에서 , 그리고 이상한 방법은 그냥 아무튼 나머지 언어로 피부를 크롤링하십시오).
그리 그러나,의 무리에 대한 lambda
애호가 – 귀도 역 추적하고 떠나기로 결심 할 때까지, 지금까지 파이썬의 역사에서 볼 반란에 가장 가까운 것 중 하나 무대 lambda
.의
에 몇 가지 추가 functools
(함수는 상수, 정체성을 반환하게하는이, 등) (이상 중복 명시 적으로 피하기 위해 일어나지 않았다 lambda
‘의 기능),하지만 partial
물론 남아의 그것은 전혀 없습니다 (한을 총 중복 않으며)는 눈에 거슬리는입니다.
기억 lambda
의 신체가로 제한된다 표현 은 한계를 가지고 있으므로. 예를 들어 … :
>>> import functools
>>> f = functools.partial(int, base=2)
>>> f.args
()
>>> f.func
<type 'int'>
>>> f.keywords
{'base': 2}
>>>
functools.partial
의 반환 함수는 내부 검사에 유용한 속성, 즉 랩핑하는 함수, 그리고 어떤 위치 및 명명 된 인수로 수정되는지로 장식됩니다. 또한 명명 된 인수를 다시 무시할 수 있습니다 ( “고정”은 다소 기본 설정입니다).
>>> f('23', base=10)
23
보시다시피 , 그것은 간단 하지 않습니다 lambda s: int(s, base=2)
!-)
예, 당신은 할 수 당신이 몇 가지 제공하기 위해 람다를 곡해 – 키워드 – 오버 라이딩을 위해, 예를
>>> f = lambda s, **k: int(s, **dict({'base': 2}, **k))
하지만 사랑스러운 희망 도 가장 열렬한 것을 lambda
-lover은 고려하지 않습니다 이 댄 공포 더 읽기 partial
전화 -!). “속성 설정”부분은 파이썬의 “본문은 단일 표현”제한으로 인해 더욱 어려워집니다 lambda
(그리고 할당은 절대로 파이썬 표현식의 일부가 될 수 없다는 사실). 디자인 한계를 넘어서 목록 이해력을 확장함으로써 … :
>>> f = [f for f in (lambda f: int(s, base=2),)
if setattr(f, 'keywords', {'base': 2}) is None][0]
이제 하나의 표현으로 명명 된 인수 overridability 플러스 세 가지 속성의 설정을, 결합, 그리고 얼마나 읽을 말해 그 … 될 것입니다!
답변
다음은 차이점을 보여주는 예입니다.
In [132]: sum = lambda x, y: x + y
In [133]: n = 5
In [134]: incr = lambda y: sum(n, y)
In [135]: incr2 = partial(sum, n)
In [136]: print incr(3), incr2(3)
8 8
In [137]: n = 9
In [138]: print incr(3), incr2(3)
12 8
Ivan Moore의 다음 게시물은 “람다의 한계”와 파이썬의 클로저를 확장합니다.
답변
최신 버전의 Python (> = 2.7)에서는 다음을 수행 할 수 있지만 다음을 수행 할 수 pickle
는 partial
없습니다 lambda
.
>>> pickle.dumps(partial(int))
'cfunctools\npartial\np0\n(c__builtin__\nint\np1\ntp2\nRp3\n(g1\n(tNNtp4\nb.'
>>> pickle.dumps(lambda x: int(x))
Traceback (most recent call last):
File "<ipython-input-11-e32d5a050739>", line 1, in <module>
pickle.dumps(lambda x: int(x))
File "/usr/lib/python2.7/pickle.py", line 1374, in dumps
Pickler(file, protocol).dump(obj)
File "/usr/lib/python2.7/pickle.py", line 224, in dump
self.save(obj)
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 748, in save_global
(obj, module, name))
PicklingError: Can't pickle <function <lambda> at 0x1729aa0>: it's not found as __main__.<lambda>
답변
functools가 어떻게 더 효율적입니까?
이것에 대한 부분 답변으로 나는 성능을 테스트하기로 결정했습니다. 내 예는 다음과 같습니다.
from functools import partial
import time, math
def make_lambda():
x = 1.3
return lambda: math.sin(x)
def make_partial():
x = 1.3
return partial(math.sin, x)
Iter = 10**7
start = time.clock()
for i in range(0, Iter):
l = make_lambda()
stop = time.clock()
print('lambda creation time {}'.format(stop - start))
start = time.clock()
for i in range(0, Iter):
l()
stop = time.clock()
print('lambda execution time {}'.format(stop - start))
start = time.clock()
for i in range(0, Iter):
p = make_partial()
stop = time.clock()
print('partial creation time {}'.format(stop - start))
start = time.clock()
for i in range(0, Iter):
p()
stop = time.clock()
print('partial execution time {}'.format(stop - start))
파이썬 3.3에서는 다음을 제공합니다.
lambda creation time 3.1743163756961392
lambda execution time 3.040552701787919
partial creation time 3.514482823352731
partial execution time 1.7113973411608114
즉, partial은 작성 시간이 조금 더 걸리지 만 실행 시간은 상당히 줄어 듭니다. 이것은 ars 의 답변에서 논의 된 초기 및 후기 바인딩의 효과 일 수 있습니다 .
답변
Alex가 언급 한 추가 기능 외에도 functools.partial의 또 다른 장점은 속도입니다. 부분적으로 다른 스택 프레임을 구성 (및 파괴)하지 않아도됩니다.
부분 또는 람다에 의해 생성 된 함수는 기본적으로 docstring을 갖지 않습니다 (단, 객체를 통해 doc 문자열을 설정할 수는 있음 __doc__
).
이 블로그에서 자세한 내용을 확인할 수 있습니다 : Python의 부분 함수 응용 프로그램
답변
세 번째 예에서 가장 빠른 의도를 이해합니다.
람다를 구문 분석 할 때 표준 라이브러리에서 직접 제공하는 것보다 더 많은 복잡성 / oddity가 예상됩니다.
또한 세 번째 예는 전체 서명에 의존하지 않는 유일한 예입니다. sum2
. 따라서 약간 느슨하게 결합됩니다.