3. Dictionaries and Sets

ve.log·2022년 11월 19일

"fluent python" 3장을 정리한 내용입니다.

Python is basically dics wrapped in loads of syntatic sugar

  • 딕셔너리 타입은, 사용자가 직접적으로 이용하지 않더라도, python의 기본 구조로써 내부에서 이용되고 있음 ( e.g. class, instance attribute, module namespaces, function key arguents )
  • __ builtins__.__dict__: 내장함수를 여기에 담고 있음
  • 파이썬에서 중요한 역할을 하고 있기 때문에, 파이썬은 dict class 에 매우 최적화 되어 있으며, 이를 위한 고성능 dict인 hash table 이 있음

1. Mordern dict Syntax

  • build, unpack, process mapping을 위한 syntax
  • dict Comprehension
    • python2.7 부터 list comprehension과 generation expression을 dict comprehension에 적용

    • example code

      country_dial = {country: code for cod country in dial_codes}
      
      {code: country.upper() 
      	for country, code in sorted(country_dial.items())}
  • unpacking mappings
    • ** 를 이용하여 하나 이상의 argument를 함수 안에서 이용가능
    • KEY 를 복사해서이용하는 것이 가능해지도록 하기때문에 키가 겹친다면 override를 기대 할 수 있다.
  • marge mappings with |
    • | 를 이용하여, mapping을 set union operation처럼 이용 가능

    • example code

      d1 = {'a': 1, 'b':3}
      d2 = {'a': 2, 'b':4, 'c':6}
      d1 | d2 
      >>> {'a':2, 'b':4, 'c':6}

2. Standard API of Mapping Types

  • collections.abc 모율은 dict 및 유사한 인터페이스를 제공하기위해 MutableMapping, Mapping abc 클래스를 제공

  • 특화된 mapping은 abc 대신 dict 이나, collections.UserDict 클래스를 상속

  • 추상 베이스 클래스는 매핑이 제공해야하는 최소한의 인터페이스를 제공, 분서화하기위한 것이며, isinstance()테스트를 하기위한 기준으로 사용
    e.g ) isinstance(dict, collections.abc.Mapping)

  • 표준 라이브러리를 제공하는 매핑형은 모두 dict형을 이용하여 구현,
    dict의 key 값은 hashable 해야하는 제한이 있음

  • hashable의 의미
    수명 주기동안 결코 변하지 않는 hash값을 가지고 있고(hash()), 다른 객체와 비료할 수 있으면(eq()) hashable 하다고 이야기
    동일하다고 판단되는 객체는 모두 해시값이 동일해야함

    • str, byte, 수치형 처럼 불변형 자료형은 모두 해시 가능

    • frozenset, tuple 해시가능

    • python이 제공하는 불변 내장 객체는 모두 해시가능하다라고 알려져 있지만, 튜플형은 불변형이긴 하나, 해시 불가능한 객체를 참조 할 수 있다.

    • user defined types: hashable
      -> id() : hash값
      -> __eq__() 메소드가 __hash__()로 생성되는 object의 id를 비교할 수 있게 되어 있기 때문에

    • 해시를 어디에 이용할까? : hash값으로 돌려받는 integer value를 dicionary key와 비교하여 값을 찾기 위해 ( 중복여부가 중요한 문제 )

      -> 따라서 항상 값이 일정해야 하므로, 변경가능한 객체는 hashable 하지 않다

3. overview of common mapping methods

  • mapping이 제공하는 기본 api 이용
  • dict, dict변형 클래스 defaultdict, OrderedDict에 구현

3.1 Inserting or Updating Mutable values

  • e.g) dict.update(m, [**kwars]) : (key,value)쌍의 매핑이나, 반복형 객체에서 가져온 항목들로 d 갱신

    • duck typing
      -> m 이 keys() method를 가지고 있는지 확인, 가지고 있다면 매핑이라고 간주
      -> keys() 없다면 update() 는 m 항목들의 key,value가 있다고 간주하고 m을 반복하여 이용
  • 존재하지 않는 키를 setdefault()로 처리하기

    • 존재하지 않는 key로 접근하면 dict은 오류를 발생
    • KeyError를 처리하는 것보다 기본 값을 사용하는 것이 편한 경우에 이용
    • 해당 객체가 가변 객체일경우__getitem__() 이나 get() 메서드를 사용하는 것이 어색한 경우에 이용
    • ditc.get() 을 이용해서 인덱스에서 발생한 단어 목록을 가져와서 갱신
      -> 키를 두번씩 검색하는 과정, 없을때는 세번
    • dict.setdecault(key, []).append(value) 를 이용하여 key에 해당하는 값이 없을경우 빈 배열을 가져오도록 설계가능
      -> 단한번만 키를 검색하고, 코드가 간결

    4. Automatic Handling of Missing Keys

    키가 존재하지 않는 경우에 , 다음과 같은 두가지 특별한 값을 반환하여 mapping에 용이하도록 이용

    1. defaultdict 사용
    2. dict의 mapping을 상속하여 __missing__() 메서드 추가

    4.1 defualtdict: Another Take on Missing Keys

  • 존재하지 않는 키로 검색할 때 요청에 따라 항목을 생성하도록 설정

  • 작동방식 : 객체를 생성할 때 존재하지 않는 키 인수로 __getitem__() 을 호출할 때마다 기본값을 생성하기위 callable제공

  • e.g. dd= defaultdic(list) 로 기본 객체를 생성하고, dd 에 존재하지 않는 key로 dd['key']를 수행하면 다음과 같은 과정을 거친다.

    1. list() 호출
    2. key를 이용하여 새로운 리스트를 dd에 삽입
    3. 리스트에대한 참조 반환
    • 기본값을 생성하는 callable은 default_factory 라는 객체 속성에 저장
    • default_factory가 생성되어있지 않으면 KeyError발생
    • defaultdict.default_fatory는 __getitem__()호출에 대한 기본 값을 제공하기위해 호출되며, 다른 메서드를 통해 호출되지 않는다.
      key가 존재하지 않는 키일 경우에,dd[key] 는 default_factory를 호출하지만 dd.get(k) 에는 단지 None을 반환
    • default_factory를 호출하게 하는 메커니즘은 __missing__() special method에 의존

    4.2 __missing__() method

  • 존재하지 않느 키 처리

  • dict클래스를 상속,__missing__()을 정의하면, dict.__getitem__() 표준메서드가 KeyError를 발생시키지 않고 __missing__()을 호출

  • in연산자를 구현하는 get(), __contains__()__missing__()에 영향을 미치지 않고, __getitem__()의 경우에만 default_factory가 작동

  • _ NOTE _
    사용자 정의형 mapping을 만들때 dict보다는 collection.UserDict클래스를 상속하는게 낫다.

profile
AI Engineer

0개의 댓글