파이썬 공부

DanA·2022년 10월 4일
0

python

목록 보기
4/4

Immutable Mappings

표준 라이브러리에서 제공하는 매핑 타입들은 모두 가변형이지만, 사용자가 실수로 매핑을 변경하지 못하도록 보장하고 싶은 경우가 있을 수 있습니다.

파이썬 3.3 이후 types 모듈은 MappingProxyType이라는 래퍼 클래스를 제공해서, 원래 매핑의 동적인 뷰를 제공하지만 읽기 전용의 mappingproxy 객체를 반환합니다. 따라서 원래 매핑을 변경하면 mappingproxy에 반영되지만, mappingproxy를 직접 변경할 수는 없습니다.

다음 코드는 mappingproxy를 사용하는 간단한 방법을 보여줍니다.

Dictionary Views

dict의 인스턴스 메소드인 .keys(), .values(), 그리고 .items()는 각각 dict_keys, dict_values, dict_items라는 클래스의 인스턴스를 반환합니다. 이 딕셔너리 뷰는 dict의 구현에서 내부 데이터 구조체의 read-only projections 입니다. Python 2에서 타겟 dict의 데이터를 복사한 리스트를 반환하는 동일한 메소드의 메모리 오버헤드를 피할 수 있게 해줍니다

다음 예제 코드는 모든 딕셔너리 뷰에서 지원되는 기본 연산자들을 보여줍니다.

Set Theory

파이썬에서 집합은 비교적 최근에 추가되었다고 볼 수 있으며, 그리 많이 사용되지는 않습니다. set 타입과 set의 불변타입인 frozenset은 파이썬 2.3에 모듈로 처음 등장했으며, 파이썬 2.6에서 built-in으로 승격되었습니다.

집합은 고유한 객체의 모음으로서, 기본적으로 중복 항목을 제거합니다.

집합의 요소들은 반드시 hashable해야 합니다. set은 해시 가능하지 않지만, frozenset은 해시 가능하므로, frozenset이 set에 들어갈 수 있습니다.

유니크하다는 것을 보장하는 것 이외에 집합 타입은 중위 연산자를 이용해서 기본적인 집합 연산을 구현합니다. 따라서 두 개의 집합 a, b가 있을 때, a | b는 합집합, a & b는 교집합, a - b는 차집합을 계산합니다. 집합 연산을 잘 사용하면 파이썬 프로그램의 소스 코드의 크기와 실행 시간을 줄일 수 있을 뿐만 아니라 루프나 조건절이 없어지므로 코드의 가독성이 높아집니다.

예를 들어 이메일 주소가 들어 있는 큰 집합(haystack)과 몇 가지 이메일 주소가 들어 있는 작은 집합(needles)이 있고, needles에 들어 있는 이메일 중 몇 개가 haystack 안에도 들어 있는지 알고 싶다고 가정해봅시다. 교집합(&) 연산자를 이용하면 다음과 같이 간단하게 작성할 수 있습니다.

found = len(needles & haystack)
교집합 연산자를 사용하지 않으면 위와 동일한 작업을 수행하기 위해 다음과 같이 구현해야 합니다.

found = 0
for n in needles:
if n in haystack:
found += 1
교집합 연산자를 사용한 코드는 사용하지 않은 코드보다 실행 속도가 약간 더 빠릅니다.

첫 번째로 살펴본 예제 코드는 두 객체가 모두 집합이어야 하는 반면, 두 번째 예제는 needles와 haystack이 iterable하다면 어느 객체든 사용할 수 있습니다. 하지만 객체가 집합형이 아니더라도 다음과 같이 즉석에서 집합으로 만들 수 있습니다.

found = len(set(needles) & set(haystack))

or,

found = len(set(needles).intersection(haystack))
물론 위 코드에서는 집합을 만드는 추가 cost가 있지만, needles나 haystack 중 하나라도 이미 집합형이라면 방금 작성한 코드가 두 번째로 살펴본 코드보다 빨리 실행될 것입니다.

앞서 설명한 예제 모두 10,000,000개의 항목을 가진 haystack 안에서 1,000개의 항목을 3밀리초 안에 검색할 수 있습니다. 즉, 항목 하나를 검색하는 데 3마이크로초 정도 걸립니다.

내부의 해시 테이블 덕분에 집합 안에 속해 있는지 여부를 아주 빨리 검색할 수 있는 것 이외에도 set과 frozenset 타입은 새로운 집합을 생성하거나, set의 경우 기존 항목을 변경하는 다양한 연산을 제공합니다.

Set Literals
{1}, {1, 2} 등 집합 리터럴에 대한 구문은 수학적 표기법과 동일하지만, 공집합은 리터럴도 표기할 수 없으므로 반드시 set()으로 표기해야 합니다. 만약 이를 사용하지 않고 {} 구문을 사용하면 딕셔너리가 생성됩니다.

파이썬 3에서는 공집합 이외의 집합을 표준 문자열로 표현하기 위해 언제나 {} 구문을 사용합니다.

{1, 2, 3}과 같은 리터럴 집합 구문은 set([1, 2, 3])처럼 생성자를 호출하는 것보다 빠르고 가독성이 좋습니다. 생성자를 명시적으로 호출하는 경우에는 파이썬이 생성자를 가져오기 위해 집합명을 검색하고, 리스트를 생성하고, 이 리스트를 생성자에 전달해야 하므로 더 느립니다. 반면 {1, 2, 3}과 같은 리터럴 집합 구문을 처리하는 경우, 파이썬은 BUILD_SET이라는 특수 바이트코드를 실행합니다.

frozenset에 대한 별도의 리터럴 구문은 없으며, frozenset은 언제나 생성자를 호출해서 생성해야 합니다. 파이썬 3에서의 표준 문자열 표현은 frozenset 생성자를 호출하는 모습과 동일합니다.

Set Comprehensions

집합 컴프리헨션(setcomp)는 위에서 언급한 dictcomp와 함께 파이썬 2.7에서 추가되었습니다. 다음 코드는 이를 이용한 간단한 예제를 보여줍니다.

Set Operations

가변형과 불변형 집합에서 사용할 수 있는 메소드들은 다음과 같습니다.

이 메소드들 중 상당수는 연산자를 오버로딩하기 위한 스페셜 메소드입니다.

이외에 메소드들은 아래의 공식 문서를 참조하시길 바랍니다.

profile
단아와라라

0개의 댓글