. 본질적으로 여러 번 실행되지만 항상 루프 본문 대신 루프 외부에서 동일한 값을 반환하는 작업을 수행합니다.
이 경우 루프는 seen
집합의 add
속성을 반복적으로 조회하고 "바운드 방식"을 만듭니다. 사실 꽤 빠르지 만 여전히 루프 내에서 여러 번 수행되는 작업이며 항상 동일한 결과를 제공합니다. 따라서 은으로 속성 (이 경우 바인딩 된 메소드)을 한 번 찾아 변수로 저장하여 성능을 향상시킬 수 있습니다.
주이 "많이"의미없이 그것의 속도 업을 제공하면서 그. 당신이 얻을 동안 중복 불가능에 ~ 그래서
# no duplicates
a = list(range(10000))
%timeit list(unique_everseen(a))
# 5.73 ms ± 279 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit list(unique_everseen_without(a))
# 6.81 ms ± 396 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# some duplicates
import random
a = [random.randint(0, 100) for _ in range(10000)]
%timeit list(unique_everseen(a))
# 1.64 ms ± 12.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit list(unique_everseen_without(a))
# 1.66 ms ± 16.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# only duplicates
a = [1]*10000
%timeit list(unique_everseen(a))
# 1.64 ms ± 78.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit list(unique_everseen_without(a))
# 1.63 ms ± 24.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
10 %의 속도 향상을 실제로 거의 쓸모 케이스 :
from itertools import filterfalse
def unique_everseen(iterable):
seen = set()
seen_add = seen.add
for element in filterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
def unique_everseen_without(iterable):
seen = set()
for element in filterfalse(seen.__contains__, iterable):
seen.add(element)
yield element
일부 exemplaric 타이밍 : 나는 코드가 짧게하는이 타이밍에 대한 두 번째 분기를 제거 많은 중복이있는 경우입니다.
실제로이 요리법은 "호이 스팅"의 또 다른 예를 보여줍니다. 구체적으로는 filterfalse(seen.__contains__, iterable)
입니다. 그러면 방법을 seen
번 찾은 다음 filterfalse
안에 반복적으로 호출합니다.
어쩌면 테이크 아웃해야합니다 : 호이 스팅 방법 조회는 마이크로 최적화입니다. 루프의 상수 요소를 줄입니다. 속도 향상은 특정 작업에서는 가치가있을 수 있지만 개인적으로는 필연적으로 프로파일 링/벤치마킹과 결합하여 사용해야한다고 생각합니다.