코드 분석 - 고성능 Python 코드 작성

짧고 효율적인 Python 코드를 작성하는 것이 항상 쉽고 간단한 것은 아닙니다. 그러나 우리는 코드 조각을 보고 그것이 작성된 방식 뒤에 있는 사고 과정을 깨닫지 못하는 경우가 많습니다. 구조를 이해하기 위해 두 iterable 간의 차이를 반환하는 difference 스니펫을 살펴보겠습니다.

스니펫의 기능에 대한 설명을 기반으로 순진하게 다음과 같이 작성할 수 있습니다.

def difference(a, b):
  return [item for item in a if item not in b]


이 구현은 충분히 잘 작동할 수 있지만 b 의 중복을 설명하지 않습니다. 이로 인해 두 번째 목록에 중복 항목이 많은 경우 코드가 필요 이상으로 오래 걸립니다. 이 문제를 해결하기 위해 목록에서 고유한 값만 유지하는 set() 메서드를 사용할 수 있습니다.

def difference(a, b):
  return [item for item in a if item not in set(b)]


이 버전은 개선된 것처럼 보이지만 실제로는 이전 버전보다 느릴 수 있습니다. 자세히 살펴보면 set()에서 item마다 a가 호출되어 set(b)의 결과가 매번 평가되는 것을 볼 수 있습니다. 다음은 문제를 더 잘 보여주기 위해 다른 방법으로 래핑set()하는 예입니다.

def difference(a, b):
  return [item for item in a if item not in make_set(b)]

def make_set(itr):
  print('Making set...')
  return set(itr)

print(difference([1, 2, 3], [1, 2, 4]))
# Making set...
# Making set...
# Making set...
# [3]


이 문제에 대한 해결책은 목록 이해 전에 한 번 set()를 호출하고 결과를 저장하여 프로세스 속도를 높이는 것입니다.

def difference(a, b):
  _b = set(b)
  return [item for item in a if item not in _b]


성능 측면에서 언급할 가치가 있는 또 다른 옵션은 목록 이해 대 filter()list() 를 사용하는 것입니다. 후자의 옵션을 사용하여 동일한 코드를 구현하면 다음과 같은 결과가 나타납니다.

def difference(a, b):
  _b = set(b)
  return list(filter(lambda item: item not in _b, a))

timeit를 사용하여 마지막 두 코드 예제의 성능을 분석하면 목록 이해를 사용하는 것이 대안보다 최대 10배 더 빠를 수 있음이 매우 분명합니다. 이것은 추가 함수 호출의 오버헤드 없이 단순for 루프와 매우 유사하게 작동하는 모국어 기능이기 때문입니다. 이것은 우리가 가독성을 제외하고 그것을 선호하는 이유를 설명합니다.

이것은 difference , symmetric_differenceintersection 과 같은 대부분의 수학적 목록 작업 스니펫에 거의 적용됩니다.


짧은 고품질 코드 스니펫과 기사가 마음에 드십니까? 우리도 그래! 이와 같은 더 많은 기사를 보려면 30 seconds of code을 방문하거나 일일 JavaScript, React 및 Python 스니펫을 보려면 팔로우하세요! 👨‍💻

좋은 웹페이지 즐겨찾기