"collections" --- 컨테이너 데이터형
***********************************

**소스 코드:** Lib/collections/__init__.py

======================================================================

이 모듈은 파이썬의 범용 내장 컨테이너 "dict", "list", "set" 및 "tuple"
에 대한 대안을 제공하는 특수 컨테이너 데이터형을 구현합니다.

+-----------------------+----------------------------------------------------------------------+
| "namedtuple()"        | 이름 붙은 필드를 갖는 튜플 서브 클래스를 만들기 위한 팩토리 함수     |
+-----------------------+----------------------------------------------------------------------+
| "deque"               | 양쪽 끝에서 빠르게 추가와 삭제를 할 수 있는 리스트류 컨테이너        |
+-----------------------+----------------------------------------------------------------------+
| "ChainMap"            | 여러 매핑의 단일 뷰를 만드는 딕셔너리류 클래스                       |
+-----------------------+----------------------------------------------------------------------+
| "Counter"             | dict subclass for counting *hashable* objects                        |
+-----------------------+----------------------------------------------------------------------+
| "OrderedDict"         | 항목이 추가된 순서를 기억하는 딕셔너리 서브 클래스                   |
+-----------------------+----------------------------------------------------------------------+
| "defaultdict"         | 누락된 값을 제공하기 위해 팩토리 함수를 호출하는 딕셔너리 서브 클래  |
|                       | 스                                                                   |
+-----------------------+----------------------------------------------------------------------+
| "UserDict"            | 더 쉬운 딕셔너리 서브 클래싱을 위해 딕셔너리 객체를 감싸는 래퍼      |
+-----------------------+----------------------------------------------------------------------+
| "UserList"            | 더 쉬운 리스트 서브 클래싱을 위해 리스트 객체를 감싸는 래퍼          |
+-----------------------+----------------------------------------------------------------------+
| "UserString"          | 더 쉬운 문자열 서브 클래싱을 위해 문자열 객체를 감싸는 래퍼          |
+-----------------------+----------------------------------------------------------------------+


"ChainMap" 객체
===============

버전 3.3에 추가.

"ChainMap" 클래스는 여러 매핑을 빠르게 연결하여 단일 단위로 취급 할 수
있도록 합니다. 종종 새로운 딕셔너리를 만들고 여러 "update()" 호출을 실
행하는 것보다 훨씬 빠릅니다.

이 클래스는 중첩된 스코프를 시뮬레이션하는 데 사용할 수 있으며 템플릿
에 유용합니다.

class collections.ChainMap(*maps)

   "ChainMap"은 여러 딕셔너리나 다른 매핑을 함께 묶어 갱신 가능한 단일
   뷰를 만듭니다. *maps*가 지정되지 않으면, 새 체인에 항상 하나 이상의
   매핑이 있도록, 빈 딕셔너리 하나가 제공됩니다.

   하부 매핑은 리스트에 저장됩니다. 이 리스트는 공개이며 *maps* 어트리
   뷰트를 사용하여 액세스하거나 갱신할 수 있습니다. 다른 상태는 없습니
   다.

   조회는 키를 찾을 때까지 하부 매핑을 검색합니다. 반면에, 쓰기, 갱신
   및 삭제는 첫 번째 매핑에만 작동합니다.

   "ChainMap"은 하부 매핑을 참조로 통합합니다. 따라서 하부 매핑 중 하
   나가 갱신되면 해당 변경 사항이 "ChainMap"에 반영됩니다.

   일반적인 딕셔너리 메서드가 모두 지원됩니다. 또한, *maps* 어트리뷰트
   , 새 서브 컨텍스트를 만드는 메서드 및 첫 번째 매핑을 제외한 모든 것
   에 액세스하는 프로퍼티가 있습니다:

   maps

      사용자 갱신 가능한 매핑 리스트. 리스트는 먼저 검색되는 것에서 나
      중에 검색되는 순서를 따릅니다. 저장된 유일한 상태이며 검색할 매
      핑을 변경하도록 수정할 수 있습니다. 리스트는 항상 하나 이상의 매
      핑이 포함되어야 합니다.

   new_child(m=None, **kwargs)

      Returns a new "ChainMap" containing a new map followed by all of
      the maps in the current instance.  If "m" is specified, it
      becomes the new map at the front of the list of mappings; if not
      specified, an empty dict is used, so that a call to
      "d.new_child()" is equivalent to: "ChainMap({}, *d.maps)". If
      any keyword arguments are specified, they update passed map or
      new empty dict. This method is used for creating subcontexts
      that can be updated without altering values in any of the parent
      mappings.

      버전 3.4에서 변경: 선택적 "m" 매개 변수가 추가되었습니다.

      버전 3.10에서 변경: Keyword arguments support was added.

   parents

      첫 번째 맵을 제외하고 현재 인스턴스의 모든 맵을 포함하는 새
      "ChainMap"을 반환하는 프로퍼티. 검색에서 첫 번째 맵을 건너뛰려고
      할 때 유용합니다. 사용 사례는 *중첩된 스코프*에서 사용되는
      "nonlocal" 키워드와 유사합니다. 사용 사례는 내장 "super()" 함수
      와도 유사합니다. "d.parents"에 대한 참조는
      "ChainMap(*d.maps[1:])"과 동등합니다.

   "ChainMap()"의 이터레이션 순서는 매핑을 마지막에서 첫 번째 방향으로
   스캔하여 결정됩니다:

      >>> baseline = {'music': 'bach', 'art': 'rembrandt'}
      >>> adjustments = {'art': 'van gogh', 'opera': 'carmen'}
      >>> list(ChainMap(adjustments, baseline))
      ['music', 'art', 'opera']

   이것은 마지막 매핑에서 시작하는 일련의 "dict.update()" 호출과 같은
   순서를 제공합니다:

      >>> combined = baseline.copy()
      >>> combined.update(adjustments)
      >>> list(combined)
      ['music', 'art', 'opera']

   버전 3.9에서 변경: **PEP 584**에 지정된, "|"와 "|=" 연산자에 대한
   지원이 추가되었습니다.

더 보기:

  * Enthought CodeTools 패키지의 MultiContext 클래스에는 체인의 모든
    매핑으로의 쓰기를 지원하는 옵션이 있습니다.

  * 템플릿을 위한 Django의 Context 클래스는 읽기 전용 매핑 체인입니다.
    또한 "new_child()" 메서드와 "parents" 프로퍼티와 유사하게 컨텍스트
    를 푸시(push)하고 팝(pop) 하는 기능이 있습니다.

  * 중첩된 컨텍스트 조리법에는 쓰기와 기타 변경이 첫 번째 매핑에만 적
    용되는지 아니면 체인의 모든 매핑에 적용되는지를 제어하는 옵션이 있
    습니다.

  * 매우 단순화된 체인 맵의 읽기 전용 버전


"ChainMap" 예제와 조리법
------------------------

이 절에서는 체인 맵으로 작업하는 다양한 접근 방식을 보여줍니다.

파이썬의 내부 조회 체인을 시뮬레이션하는 예:

   import builtins
   pylookup = ChainMap(locals(), globals(), vars(builtins))

사용자 지정 명령 줄 인자가 환경 변수보다 우선하고, 환경 변수는 기본값
보다 우선하도록 하는 예:

   import os, argparse

   defaults = {'color': 'red', 'user': 'guest'}

   parser = argparse.ArgumentParser()
   parser.add_argument('-u', '--user')
   parser.add_argument('-c', '--color')
   namespace = parser.parse_args()
   command_line_args = {k: v for k, v in vars(namespace).items() if v is not None}

   combined = ChainMap(command_line_args, os.environ, defaults)
   print(combined['color'])
   print(combined['user'])

중첩된 컨텍스트를 시뮬레이션하기 위해 "ChainMap" 클래스를 사용하는 예
제 패턴:

   c = ChainMap()        # Create root context
   d = c.new_child()     # Create nested child context
   e = c.new_child()     # Child of c, independent from d
   e.maps[0]             # Current context dictionary -- like Python's locals()
   e.maps[-1]            # Root context -- like Python's globals()
   e.parents             # Enclosing context chain -- like Python's nonlocals

   d['x'] = 1            # Set value in current context
   d['x']                # Get first key in the chain of contexts
   del d['x']            # Delete from current context
   list(d)               # All nested values
   k in d                # Check all nested values
   len(d)                # Number of nested values
   d.items()             # All nested items
   dict(d)               # Flatten into a regular dictionary

"ChainMap" 클래스는 체인의 첫 번째 매핑만 갱신(쓰기와 삭제)하지만, 조
회는 전체 체인을 검색합니다. 그러나, 깊은 쓰기와 삭제가 필요하면, 체인
의 더 깊은 곳에서 발견된 키를 갱신하는 서브 클래스를 쉽게 만들 수 있습
니다:

   class DeepChainMap(ChainMap):
       'Variant of ChainMap that allows direct updates to inner scopes'

       def __setitem__(self, key, value):
           for mapping in self.maps:
               if key in mapping:
                   mapping[key] = value
                   return
           self.maps[0][key] = value

       def __delitem__(self, key):
           for mapping in self.maps:
               if key in mapping:
                   del mapping[key]
                   return
           raise KeyError(key)

   >>> d = DeepChainMap({'zebra': 'black'}, {'elephant': 'blue'}, {'lion': 'yellow'})
   >>> d['lion'] = 'orange'         # update an existing key two levels down
   >>> d['snake'] = 'red'           # new keys get added to the topmost dict
   >>> del d['elephant']            # remove an existing key one level down
   >>> d                            # display result
   DeepChainMap({'zebra': 'black', 'snake': 'red'}, {}, {'lion': 'orange'})


"Counter" 객체
==============

편리하고 빠르게 개수를 세도록 지원하는 계수기 도구가 제공됩니다. 예를
들면:

   >>> # Tally occurrences of words in a list
   >>> cnt = Counter()
   >>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
   ...     cnt[word] += 1
   >>> cnt
   Counter({'blue': 3, 'red': 2, 'green': 1})

   >>> # Find the ten most common words in Hamlet
   >>> import re
   >>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())
   >>> Counter(words).most_common(10)
   [('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
    ('you', 554),  ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]

class collections.Counter([iterable-or-mapping])

   A "Counter" is a "dict" subclass for counting *hashable* objects.
   It is a collection where elements are stored as dictionary keys and
   their counts are stored as dictionary values.  Counts are allowed
   to be any integer value including zero or negative counts.  The
   "Counter" class is similar to bags or multisets in other languages.

   요소는 *이터러블*로부터 계산되거나 다른 *매핑*(또는 계수기)에서 초
   기화됩니다:

   >>> c = Counter()                           # a new, empty counter
   >>> c = Counter('gallahad')                 # a new counter from an iterable
   >>> c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
   >>> c = Counter(cats=4, dogs=8)             # a new counter from keyword args

   계수기 객체는 누락된 항목에 대해 "KeyError"를 발생시키는 대신 0을
   반환한다는 점을 제외하고 딕셔너리 인터페이스를 갖습니다:

   >>> c = Counter(['eggs', 'ham'])
   >>> c['bacon']                              # count of a missing element is zero
   0

   개수를 0으로 설정해도 계수기에서 요소가 제거되지 않습니다. 완전히
   제거하려면 "del"을 사용하십시오:

   >>> c['sausage'] = 0                        # counter entry with a zero count
   >>> del c['sausage']                        # del actually removes the entry

   버전 3.1에 추가.

   버전 3.7에서 변경: As a "dict" subclass, "Counter" inherited the
   capability to remember insertion order.  Math operations on
   *Counter* objects also preserve order.  Results are ordered
   according to when an element is first encountered in the left
   operand and then by the order encountered in the right operand.

   Counter objects support additional methods beyond those available
   for all dictionaries:

   elements()

      개수만큼 반복되는 요소에 대한 이터레이터를 반환합니다. 요소는 처
      음 발견되는 순서대로 반환됩니다. 요소의 개수가 1보다 작으면
      "elements()"는 이를 무시합니다.

      >>> c = Counter(a=4, b=2, c=0, d=-2)
      >>> sorted(c.elements())
      ['a', 'a', 'a', 'a', 'b', 'b']

   most_common([n])

      *n* 개의 가장 흔한 요소와 그 개수를 가장 흔한 것부터 가장 적은
      것 순으로 나열한 리스트를 반환합니다. *n*이 생략되거나 "None"이
      면, "most_common()"은 계수기의 *모든* 요소를 반환합니다. 개수가
      같은 요소는 처음 발견된 순서를 유지합니다:

      >>> Counter('abracadabra').most_common(3)
      [('a', 5), ('b', 2), ('r', 2)]

   subtract([iterable-or-mapping])

      *이터러블*이나 다른 *매핑* (또는 계수기)으로부터 온 요소들을 뺍
      니다. "dict.update()"와 비슷하지만 교체하는 대신 개수를 뺍니다.
      입력과 출력 모두 0이나 음수일 수 있습니다.

      >>> c = Counter(a=4, b=2, c=0, d=-2)
      >>> d = Counter(a=1, b=2, c=3, d=4)
      >>> c.subtract(d)
      >>> c
      Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})

      버전 3.2에 추가.

   total()

      Compute the sum of the counts.

      >>> c = Counter(a=10, b=5, c=0)
      >>> c.total()
      15

      버전 3.10에 추가.

   일반적인 딕셔너리 메서드를 "Counter" 객체에 사용할 수 있습니다만,
   두 메서드는 계수기에서 다르게 동작합니다.

   fromkeys(iterable)

      이 클래스 메서드는 "Counter" 객체에 구현되지 않았습니다.

   update([iterable-or-mapping])

      요소는 *이터러블*에서 세거나 다른 *매핑*(또는 계수기)에서 더해집
      니다. "dict.update()"와 비슷하지만, 교체하는 대신 더합니다. 또한
      , *이터러블*은 "(key, value)" 쌍의 시퀀스가 아닌, 요소의 시퀀스
      일 것으로 기대합니다.

Counters support rich comparison operators for equality, subset, and
superset relationships: "==", "!=", "<", "<=", ">", ">=". All of those
tests treat missing elements as having zero counts so that
"Counter(a=1) == Counter(a=1, b=0)" returns true.

버전 3.10에 추가: Rich comparison operations were added.

버전 3.10에서 변경: In equality tests, missing elements are treated as
having zero counts. Formerly, "Counter(a=3)" and "Counter(a=3, b=0)"
were considered distinct.

"Counter" 객체로 작업하는 일반적인 패턴:

   c.total()                       # total of all counts
   c.clear()                       # reset all counts
   list(c)                         # list unique elements
   set(c)                          # convert to a set
   dict(c)                         # convert to a regular dictionary
   c.items()                       # convert to a list of (elem, cnt) pairs
   Counter(dict(list_of_pairs))    # convert from a list of (elem, cnt) pairs
   c.most_common()[:-n-1:-1]       # n least common elements
   +c                              # remove zero and negative counts

Several mathematical operations are provided for combining "Counter"
objects to produce multisets (counters that have counts greater than
zero). Addition and subtraction combine counters by adding or
subtracting the counts of corresponding elements.  Intersection and
union return the minimum and maximum of corresponding counts.
Equality and inclusion compare corresponding counts.  Each operation
can accept inputs with signed counts, but the output will exclude
results with counts of zero or less.

   >>> c = Counter(a=3, b=1)
   >>> d = Counter(a=1, b=2)
   >>> c + d                       # add two counters together:  c[x] + d[x]
   Counter({'a': 4, 'b': 3})
   >>> c - d                       # subtract (keeping only positive counts)
   Counter({'a': 2})
   >>> c & d                       # intersection:  min(c[x], d[x])
   Counter({'a': 1, 'b': 1})
   >>> c | d                       # union:  max(c[x], d[x])
   Counter({'a': 3, 'b': 2})
   >>> c == d                      # equality:  c[x] == d[x]
   False
   >>> c <= d                      # inclusion:  c[x] <= d[x]
   False

단항 덧셈과 뺄셈은 빈 계수기를 더하거나 빈 계수기를 빼는 것의 줄임 표
현입니다.

>>> c = Counter(a=2, b=-4)
>>> +c
Counter({'a': 2})
>>> -c
Counter({'b': 4})

버전 3.3에 추가: 단항 플러스, 단항 마이너스 및 제자리 멀티 셋 연산에
대한 지원이 추가되었습니다.

참고:

  계수기는 주로 양의 정수로 작동하여 횟수를 나타내도록 설계되었습니다;
  그러나, 다른 형이나 음수 값이 필요한 사용 사례를 불필요하게 배제하지
  않도록 주의를 기울였습니다. 이러한 사용 사례에 도움이 되도록, 이 절
  은 최소 범위와 형 제약 사항을 설명합니다.

  * "Counter" 클래스 자체는 키와 값에 제한이 없는 딕셔너리 서브 클래스
    입니다. 값은 개수를 나타내는 숫자로 의도되었지만, 값 필드에 어떤
    것이든 저장할 *수* 있습니다.

  * "most_common()" 메서드는 값에 대해 순서만을 요구합니다.

  * "c[key] += 1"과 같은 제자리 연산의 경우, 값 형은 덧셈과 뺄셈만 지
    원하면 됩니다. 따라서 분수(fractions), 부동 소수점(floats) 및 십진
    수(decimals)가 작동하고 음수 값이 지원됩니다. "update()"와
    "subtract()"에 대해서도 마찬가지인데, 입력과 출력 모두 음수와 0을
    허용합니다.

  * 멀티 셋(multiset) 메서드는 양의 값에 대한 사용 사례를 위해서만 설
    계되었습니다. 입력은 음수이거나 0일 수 있지만, 양수 값을 갖는 출력
    만 만들어집니다. 형 제한은 없지만, 값 형은 더하기, 빼기 및 비교를
    지원해야 합니다.

  * "elements()" 메서드는 정수 개수를 요구합니다. 0과 음수 개수는 무시
    합니다.

더 보기:

  * 스몰토크(Smalltalk)의 Bag 클래스.

  * Multisets에 대한 위키피디아 항목.

  * 예제가 포함된 C++ multisets 자습서.

  * 멀티 셋에 대한 수학 연산과 그 사용 사례에 대해서는, *Knuth,
    Donald. The Art of Computer Programming Volume II, Section 4.6.3,
    Exercise 19*를 참조하십시오.

  * 주어진 요소 집합에 대해 주어진 크기의 모든 서로 다른 멀티 셋을 열
    거하려면, "itertools.combinations_with_replacement()"를 참조하십시
    오:

       map(Counter, combinations_with_replacement('ABC', 2)) # --> AA AB AC BB BC CC


"deque" 객체
============

class collections.deque([iterable[, maxlen]])

   *iterable*의 데이터로 왼쪽에서 오른쪽으로 ("append()"를 사용해서)
   초기화된 새 데크(deque) 객체를 반환합니다. *iterable*을 지정하지 않
   으면, 새 데크는 비어 있습니다.

   데크는 스택과 큐를 일반화 한 것입니다 (이름은 "deck"이라고 발음하며
   "double-ended queue"의 약자입니다). 데크는 스레드 안전하고 메모리
   효율적인 데크의 양쪽 끝에서의 추가(append)와 팝(pop)을 양쪽에서 거
   의 같은 O(1) 성능으로 지원합니다.

   "list" 객체는 유사한 연산을 지원하지만, 빠른 고정 길이 연산에 최적
   화되어 있으며, 하부 데이터 표현의 크기와 위치를 모두 변경하는
   "pop(0)"과 "insert(0, v)" 연산에 대해 O(n) 메모리 이동 비용이 발생
   합니다.

   *maxlen*이 지정되지 않거나 "None"이면, 데크는 임의의 길이로 커질 수
   있습니다. 그렇지 않으면, 데크는 지정된 최대 길이로 제한됩니다. 일단
   제한된 길이의 데크가 가득 차면, 새 항목이 추가될 때, 해당하는 수의
   항목이 반대쪽 끝에서 삭제됩니다. 제한된 길이의 데크는 유닉스의
   "tail" 필터와 유사한 기능을 제공합니다. 또한 가장 최근 활동만 관심
   이 있는 트랜잭션과 기타 데이터 풀을 추적하는 데 유용합니다.

   deque 객체는 다음 메서드를 지원합니다:

   append(x)

      데크의 오른쪽에 *x*를 추가합니다.

   appendleft(x)

      데크의 왼쪽에 *x*를 추가합니다.

   clear()

      데크에서 모든 요소를 제거하고 길이가 0인 상태로 만듭니다.

   copy()

      데크의 얕은 복사본을 만듭니다.

      버전 3.5에 추가.

   count(x)

      *x* 와 같은 데크 요소의 수를 셉니다.

      버전 3.2에 추가.

   extend(iterable)

      iterable 인자에서 온 요소를 추가하여 데크의 오른쪽을 확장합니다.

   extendleft(iterable)

      *iterable*에서 온 요소를 추가하여 데크의 왼쪽을 확장합니다. 일련
      의 왼쪽 추가는 iterable 인자에 있는 요소의 순서를 뒤집는 결과를
      줍니다.

   index(x[, start[, stop]])

      데크에 있는 *x*의 위치를 반환합니다 (인덱스 *start* 또는 그 이후
      , 그리고 인덱스 *stop* 이전). 첫 번째 일치를 반환하거나 찾을 수
      없으면 "ValueError"를 발생시킵니다.

      버전 3.5에 추가.

   insert(i, x)

      *x*를 데크의 *i* 위치에 삽입합니다.

      삽입으로 인해 제한된 길이의 데크가 *maxlen* 이상으로 커지면,
      "IndexError"가 발생합니다.

      버전 3.5에 추가.

   pop()

      데크의 오른쪽에서 요소를 제거하고 반환합니다. 요소가 없으면,
      "IndexError"를 발생시킵니다.

   popleft()

      데크의 왼쪽에서 요소를 제거하고 반환합니다. 요소가 없으면,
      "IndexError"를 발생시킵니다.

   remove(value)

      *value*의 첫 번째 항목을 제거합니다. 찾을 수 없으면,
      "ValueError"를 발생시킵니다.

   reverse()

      데크의 요소들을 제자리에서 순서를 뒤집고 "None"을 반환합니다.

      버전 3.2에 추가.

   rotate(n=1)

      데크를 *n* 단계 오른쪽으로 회전합니다. *n*이 음수이면, 왼쪽으로
      회전합니다.

      데크가 비어 있지 않으면, 오른쪽으로 한 단계 회전하는 것은
      "d.appendleft(d.pop())"과 동등하고, 왼쪽으로 한 단계 회전하는 것
      은 "d.append(d.popleft())"와 동등합니다.

   데크 객체는 하나의 읽기 전용 어트리뷰트도 제공합니다:

   maxlen

      데크의 최대 크기 또는 제한이 없으면 "None".

      버전 3.1에 추가.

상기한 것들 외에도, 데크는 이터레이션, 피클링, "len(d)",
"reversed(d)", "copy.copy(d)", "copy.deepcopy(d)", "in" 연산자를 사용
한 멤버십 검사 및 첫 번째 요소를 액세스하는 "d[0]"과 같은 서브 스크립
트 참조를 지원합니다. 인덱스를 사용하는 액세스는 양쪽 끝에서는 O(1) 이
지만 중간에서는 O(n) 으로 느려집니다. 빠른 무작위 액세스를 위해서는 대
신 리스트를 사용하십시오.

버전 3.5부터, 데크는 "__add__()", "__mul__()" 및 "__imul__()"을 지원합
니다.

예:

   >>> from collections import deque
   >>> d = deque('ghi')                 # make a new deque with three items
   >>> for elem in d:                   # iterate over the deque's elements
   ...     print(elem.upper())
   G
   H
   I

   >>> d.append('j')                    # add a new entry to the right side
   >>> d.appendleft('f')                # add a new entry to the left side
   >>> d                                # show the representation of the deque
   deque(['f', 'g', 'h', 'i', 'j'])

   >>> d.pop()                          # return and remove the rightmost item
   'j'
   >>> d.popleft()                      # return and remove the leftmost item
   'f'
   >>> list(d)                          # list the contents of the deque
   ['g', 'h', 'i']
   >>> d[0]                             # peek at leftmost item
   'g'
   >>> d[-1]                            # peek at rightmost item
   'i'

   >>> list(reversed(d))                # list the contents of a deque in reverse
   ['i', 'h', 'g']
   >>> 'h' in d                         # search the deque
   True
   >>> d.extend('jkl')                  # add multiple elements at once
   >>> d
   deque(['g', 'h', 'i', 'j', 'k', 'l'])
   >>> d.rotate(1)                      # right rotation
   >>> d
   deque(['l', 'g', 'h', 'i', 'j', 'k'])
   >>> d.rotate(-1)                     # left rotation
   >>> d
   deque(['g', 'h', 'i', 'j', 'k', 'l'])

   >>> deque(reversed(d))               # make a new deque in reverse order
   deque(['l', 'k', 'j', 'i', 'h', 'g'])
   >>> d.clear()                        # empty the deque
   >>> d.pop()                          # cannot pop from an empty deque
   Traceback (most recent call last):
       File "<pyshell#6>", line 1, in -toplevel-
           d.pop()
   IndexError: pop from an empty deque

   >>> d.extendleft('abc')              # extendleft() reverses the input order
   >>> d
   deque(['c', 'b', 'a'])


"deque" 조리법
--------------

이 절은 데크로 작업하는 다양한 접근 방식을 보여줍니다.

제한된 길이의 데크는 유닉스의 "tail" 필터와 유사한 기능을 제공합니다:

   def tail(filename, n=10):
       'Return the last n lines of a file'
       with open(filename) as f:
           return deque(f, n)

데크를 사용하는 또 다른 접근법은 오른쪽에 추가하고 왼쪽에서 팝 하여 최
근에 추가된 요소의 시퀀스를 유지하는 것입니다:

   def moving_average(iterable, n=3):
       # moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0
       # https://en.wikipedia.org/wiki/Moving_average
       it = iter(iterable)
       d = deque(itertools.islice(it, n-1))
       d.appendleft(0)
       s = sum(d)
       for elem in it:
           s += elem - d.popleft()
           d.append(elem)
           yield s / n

라운드 로빈 스케줄러(round-robin scheduler)는 "deque"에 저장된 입력 이
터레이터로 구현할 수 있습니다. 위치 0에 있는 활성 이터레이터에서 값이
산출됩니다. 그 이터레이터가 소진되면, "popleft()"로 제거할 수 있습니다
; 그렇지 않으면, "rotate()" 메서드로 끝으로 보내 순환할 수 있습니다:

   def roundrobin(*iterables):
       "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
       iterators = deque(map(iter, iterables))
       while iterators:
           try:
               while True:
                   yield next(iterators[0])
                   iterators.rotate(-1)
           except StopIteration:
               # Remove an exhausted iterator.
               iterators.popleft()

"rotate()" 메서드는 "deque" 슬라이싱과 삭제를 구현하는 방법을 제공합니
다. 예를 들어, "del d[n]"의 순수 파이썬 구현은 팝 될 요소의 위치를 잡
기 위해 "rotate()" 메서드에 의존합니다:

   def delete_nth(d, n):
       d.rotate(-n)
       d.popleft()
       d.rotate(n)

"deque" 슬라이싱을 구현하려면, 대상 요소를 데크의 왼쪽으로 가져오기 위
해 "rotate()"를 적용하는 유사한 접근법을 사용하십시오. "popleft()"로
이전 항목을 제거하고, "extend()"로 새 항목을 추가한 다음, 회전을 되돌
립니다. 이 접근 방식에 약간의 변형을 가하면, "dup", "drop", "swap",
"over", "pick", "rot" 및 "roll"과 같은 Forth 스타일 스택 조작을 쉽게
구현할 수 있습니다.


"defaultdict" 객체
==================

class collections.defaultdict(default_factory=None, /[, ...])

   Return a new dictionary-like object.  "defaultdict" is a subclass
   of the built-in "dict" class.  It overrides one method and adds one
   writable instance variable.  The remaining functionality is the
   same as for the "dict" class and is not documented here.

   첫 번째 인자는 "default_factory" 어트리뷰트의 초깃값을 제공합니다;
   기본값은 "None"입니다. 나머지 모든 인자는 키워드 인자를 포함하여
   "dict" 생성자에 전달될 때와 마찬가지로 취급됩니다.

   "defaultdict" 객체는 표준 "dict" 연산 외에도 다음 메서드를 지원합니
   다:

   __missing__(key)

      "default_factory" 어트리뷰트가 "None"이면, *key*를 인자로 사용하
      는 "KeyError" 예외가 발생합니다.

      "default_factory"가 "None"이 아니면, 주어진 *key*에 대한 기본값
      을 제공하기 위해 인자 없이 호출되며, 반환 값은 *key*로 딕셔너리
      에 삽입되고 반환됩니다.

      "default_factory"를 호출할 때 예외가 발생하면 이 예외는 변경되지
      않고 전파됩니다.

      이 메서드는 요청된 키를 찾을 수 없을 때 "dict" 클래스의
      "__getitem__()" 메서드에 의해 호출됩니다; 이것이 반환하거나 발생
      시키는 모든 것은, "__getitem__()"이 반환하거나 발생시킵니다.

      "__missing__()"은 "__getitem__()" 이외의 어떤 연산에서도 호출되
      지 *않음*에 유의하십시오. 이것은 "get()"이 일반 딕셔너리와 마찬
      가지로 "default_factory"를 사용하지 않고 "None"을 기본값으로 반
      환한다는 것을 의미합니다.

   "defaultdict" 객체는 다음 인스턴스 변수를 지원합니다:

   default_factory

      이 어트리뷰트는 "__missing__()" 메서드에서 사용됩니다; 생성자의
      첫 번째 인자가 있으면 그것으로, 없으면 "None"으로 초기화됩니다.

   버전 3.9에서 변경: **PEP 584**에 지정된, 병합("|")과 업데이트("|=")
   연산자가 추가되었습니다.


"defaultdict" 예
----------------

"list"를 "default_factory"로 사용하면, 키-값 쌍의 시퀀스를 리스트의 딕
셔너리로 쉽게 그룹화 할 수 있습니다:

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

각 키가 처음 발견될 때, 아직 매핑에 있지 않게 됩니다; 그래서
"default_factory" 함수를 사용하여 항목이 자동으로 만들어지는데, 빈
"list"를 반환합니다. 그런 다음 "list.append()" 연산이 값을 새 리스트에
추가합니다. 키를 다시 만나면, 조회가 정상적으로 진행되고 (해당 키의 리
스트를 반환합니다), "list.append()" 연산은 다른 값을 리스트에 추가합니
다. 이 기법은 "dict.setdefault()"를 사용하는 동등한 기법보다 간단하고
빠릅니다:

>>> d = {}
>>> for k, v in s:
...     d.setdefault(k, []).append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

"default_factory"를 "int"로 설정하면 "defaultdict"를 세는(counting) 데
유용하게 사용할 수 있습니다 (다른 언어의 백(bag)이나 멀티 셋(multiset)
처럼):

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
...     d[k] += 1
...
>>> sorted(d.items())
[('i', 4), ('m', 1), ('p', 2), ('s', 4)]

글자가 처음 발견될 때, 매핑에서 누락되었으므로, "default_factory" 함수
는 "int()"를 호출하여 기본 계수 0을 제공합니다. 증분 연산은 각 문자의
개수를 쌓아나갑니다.

항상 0을 반환하는 함수 "int()"는 상수 함수의 특별한 경우일 뿐입니다.
상수 함수를 만드는 더 빠르고 유연한 방법은 (단지 0이 아니라) 임의의 상
숫값을 제공 할 수 있는 람다 함수를 사용하는 것입니다:

>>> def constant_factory(value):
...     return lambda: value
>>> d = defaultdict(constant_factory('<missing>'))
>>> d.update(name='John', action='ran')
>>> '%(name)s %(action)s to %(object)s' % d
'John ran to <missing>'

"default_factory"를 "set"으로 설정하면, "defaultdict"를 집합의 딕셔너
리를 만드는 데 유용하게 만듭니다:

>>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
>>> d = defaultdict(set)
>>> for k, v in s:
...     d[k].add(v)
...
>>> sorted(d.items())
[('blue', {2, 4}), ('red', {1, 3})]


이름있는 필드를 가진 튜플을 위한 "namedtuple()" 팩토리 함수
===========================================================

네임드 튜플은 튜플의 각 위치에 의미를 부여하고 더 읽기 쉽고 스스로 설
명하는 코드를 만들도록 합니다. 일반 튜플이 사용되는 곳이라면 어디에서
나 사용할 수 있으며, 위치 인덱스 대신 이름으로 필드에 액세스하는 기능
을 추가합니다.

collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)

   *typename*이라는 이름의 새 튜플 서브 클래스를 반환합니다. 새로운 서
   브 클래스는 인덱싱되고 이터러블일 뿐만 아니라 어트리뷰트 조회로 액
   세스 할 수 있는 필드를 갖는 튜플류 객체를 만드는 데 사용됩니다. 서
   브 클래스의 인스턴스에는 유용한 독스트링(typename과 field_names를
   포함합니다)과 튜플 내용을 "name=value" 형식으로 나열하는 유용한
   "__repr__()" 메서드가 있습니다.

   *field_names*는 "['x', 'y']"와 같은 문자열의 시퀀스입니다. 또는,
   *field_names*는 각 필드명이 공백 및/또는 쉼표로 구분된 단일 문자열
   일 수 있습니다, 예를 들어 "'x y'"나 "'x, y'".

   밑줄로 시작하는 이름을 제외한 모든 유효한 파이썬 식별자를 필드명에
   사용할 수 있습니다. 유효한 식별자는 글자, 숫자 및 밑줄로 구성되지만
   , 숫자나 밑줄로 시작하지 않으며 *class*, *for*, *return*, *global*,
   *pass* 또는 *raise*와 같은 "keyword"일 수 없습니다.

   *rename*이 참이면, 유효하지 않은 필드명은 위치 이름으로 자동 대체됩
   니다. 예를 들어, "['abc', 'def', 'ghi', 'abc']"는 "['abc', '_1',
   'ghi', '_3']"으로 변환되어 키워드 "def"와 중복된 필드명 "abc"를 제
   거합니다.

   *defaults*는 "None"이나 기본값의 *이터러블* 일 수 있습니다. 기본값
   이 있는 필드는 기본값이 없는 필드 뒤에 와야 하므로, *defaults*는 가
   장 오른쪽의 매개 변수에 적용됩니다. 예를 들어, field_names가 "['x',
   'y', 'z']"이고 defaults가 "(1, 2)"이면 "x"는 필수 인자이고, "y"의
   기본값은 "1", "z"의 기본값은 "2"입니다.

   *module*이 정의되면, 네임드 튜플의 "__module__" 어트리뷰트가 해당
   값으로 설정됩니다.

   네임드 튜플 인스턴스에는 인스턴스 별 딕셔너리가 없어서, 가볍고 일반
   튜플보다 더 많은 메모리가 필요하지 않습니다.

   피클링을 지원하려면, 네임드 튜플 클래스를 *typename*과 일치하는 변
   수에 대입해야 합니다.

   버전 3.1에서 변경: *rename*에 대한 지원이 추가되었습니다.

   버전 3.6에서 변경: *verbose*와 *rename* 매개 변수는 키워드 전용 인
   자가 되었습니다.

   버전 3.6에서 변경: *module* 매개 변수를 추가했습니다.

   버전 3.7에서 변경: *verbose* 매개 변수와 "_source" 어트리뷰트를 제
   거했습니다.

   버전 3.7에서 변경: *defaults* 매개 변수와 "_field_defaults" 어트리
   뷰트가 추가되었습니다.

   >>> # Basic example
   >>> Point = namedtuple('Point', ['x', 'y'])
   >>> p = Point(11, y=22)     # instantiate with positional or keyword arguments
   >>> p[0] + p[1]             # indexable like the plain tuple (11, 22)
   33
   >>> x, y = p                # unpack like a regular tuple
   >>> x, y
   (11, 22)
   >>> p.x + p.y               # fields also accessible by name
   33
   >>> p                       # readable __repr__ with a name=value style
   Point(x=11, y=22)

네임드 튜플은 "csv" 나 "sqlite3" 모듈이 반환한 결과 튜플에 필드 이름을
할당하는 데 특히 유용합니다:

   EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')

   import csv
   for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
       print(emp.name, emp.title)

   import sqlite3
   conn = sqlite3.connect('/companydata')
   cursor = conn.cursor()
   cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
   for emp in map(EmployeeRecord._make, cursor.fetchall()):
       print(emp.name, emp.title)

튜플에서 상속된 메서드 외에도 네임드 튜플은 세 가지 추가 메서드와 두
가지 어트리뷰트를 지원합니다. 필드 이름과의 충돌을 방지하기 위해, 메서
드와 어트리뷰트 이름은 밑줄로 시작합니다.

classmethod somenamedtuple._make(iterable)

   기존 시퀀스나 이터러블로 새 인스턴스를 만드는 클래스 메서드.

      >>> t = [11, 22]
      >>> Point._make(t)
      Point(x=11, y=22)

somenamedtuple._asdict()

   필드 이름을 해당 값으로 매핑하는 새 "dict"를 반환합니다:

      >>> p = Point(x=11, y=22)
      >>> p._asdict()
      {'x': 11, 'y': 22}

   버전 3.1에서 변경: 일반 "dict" 대신 "OrderedDict"를 반환합니다.

   버전 3.8에서 변경: "OrderedDict" 대신 일반 "dict"를 반환합니다. 파
   이썬 3.7부터, 일반 딕셔너리의 순서가 유지되도록 보장합니다.
   "OrderedDict"의 추가 기능이 필요할 때, 제안하는 처방은 결과를 원하
   는 형으로 캐스트 하는 것입니다: "OrderedDict(nt._asdict())".

somenamedtuple._replace(**kwargs)

   지정된 필드들을 새로운 값으로 치환하는 네임드 튜플의 새 인스턴스를
   반환합니다:

      >>> p = Point(x=11, y=22)
      >>> p._replace(x=33)
      Point(x=33, y=22)

      >>> for partnum, record in inventory.items():
      ...     inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())

somenamedtuple._fields

   필드 이름을 나열하는 문자열의 튜플. 인트로스펙션과 기존 네임드 튜플
   에서 새로운 네임드 튜플 형을 만드는 데 유용합니다.

      >>> p._fields            # view the field names
      ('x', 'y')

      >>> Color = namedtuple('Color', 'red green blue')
      >>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)
      >>> Pixel(11, 22, 128, 255, 0)
      Pixel(x=11, y=22, red=128, green=255, blue=0)

somenamedtuple._field_defaults

   필드 이름을 기본값으로 매핑하는 딕셔너리.

      >>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
      >>> Account._field_defaults
      {'balance': 0}
      >>> Account('premium')
      Account(type='premium', balance=0)

이름이 문자열에 저장된 필드를 조회하려면 "getattr()" 함수를 사용하십시
오.:

>>> getattr(p, 'x')
11

딕셔너리를 네임드 튜플로 변환하려면 이중 애스터리스크 연산자를 사용하
십시오 (인자 목록 언 패킹에서 설명합니다).:

>>> d = {'x': 11, 'y': 22}
>>> Point(**d)
Point(x=11, y=22)

네임드 튜플은 일반적인 파이썬 클래스이므로, 서브 클래스를 사용하여 기
능을 쉽게 추가하거나 변경할 수 있습니다. 계산된 필드와 고정 너비 인쇄
포맷을 추가하는 방법은 다음과 같습니다:

   >>> class Point(namedtuple('Point', ['x', 'y'])):
   ...     __slots__ = ()
   ...     @property
   ...     def hypot(self):
   ...         return (self.x ** 2 + self.y ** 2) ** 0.5
   ...     def __str__(self):
   ...         return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)

   >>> for p in Point(3, 4), Point(14, 5/7):
   ...     print(p)
   Point: x= 3.000  y= 4.000  hypot= 5.000
   Point: x=14.000  y= 0.714  hypot=14.018

위에 표시된 서브 클래스는 "__slots__"를 빈 튜플로 설정합니다. 이렇게
하면 인스턴스 딕셔너리 생성을 방지하여 메모리 요구 사항을 낮게 유지할
수 있습니다.

서브 클래싱은 저장된 새 필드를 추가하는 데는 유용하지 않습니다. 대신,
"_fields" 어트리뷰트로 새로운 네임드 튜플 형을 만드십시오:

>>> Point3D = namedtuple('Point3D', Point._fields + ('z',))

"__doc__" 필드에 직접 대입하여 독스트링을 사용자 정의할 수 있습니다:

>>> Book = namedtuple('Book', ['id', 'title', 'authors'])
>>> Book.__doc__ += ': Hardcover book in active collection'
>>> Book.id.__doc__ = '13-digit ISBN'
>>> Book.title.__doc__ = 'Title of first printing'
>>> Book.authors.__doc__ = 'List of authors sorted by last name'

버전 3.5에서 변경: 프로퍼티 독스트링이 쓰기 가능하게 되었습니다.

더 보기:

  * 네임드 튜플에 형 힌트를 추가하는 방법은 "typing.NamedTuple"을 참조
    하십시오. 이것은 "class" 키워드를 사용하는 우아한 표기법도 제공합
    니다:

       class Component(NamedTuple):
           part_number: int
           weight: float
           description: Optional[str] = None

  * 튜플 대신 하부 딕셔너리를 기반으로 하는 가변 이름 공간에 대해서는
    "types.SimpleNamespace()"를 참조하십시오.

  * "dataclasses" 모듈은 사용자 정의 클래스에 생성된 특수 메서드를 자
    동으로 추가하는 데코레이터와 함수를 제공합니다.


"OrderedDict" 객체
==================

순서 있는 딕셔너리는 일반 딕셔너리와 비슷하지만, 순서를 다루는 연산과
관련된 몇 가지 추가 기능이 있습니다. 내장 "dict" 클래스가 삽입 순서를
기억하는 기능을 얻었으므로 (이 새로운 동작은 파이썬 3.7에서 보장되었습
니다), 이제 덜 중요해졌습니다.

몇 가지 "dict"와의 차이점은 여전히 남아 있습니다:

* 일반 "dict"는 매핑 연산에 매우 적합하도록 설계되었습니다. 삽입 순서
  추적은 부차적입니다.

* "OrderedDict"는 순서를 바꾸는 연산에 적합하도록 설계되었습니다. 공간
  효율성, 이터레이션 속도 및 갱신 연산의 성능은 부차적입니다.

* The "OrderedDict" algorithm can handle frequent reordering
  operations better than "dict".  As shown in the recipes below, this
  makes it suitable for implementing various kinds of LRU caches.

* "OrderedDict"의 동등 비교 연산은 순서의 일치를 확인합니다.

  A regular "dict" can emulate the order sensitive equality test with
  "p == q and all(k1 == k2 for k1, k2 in zip(p, q))".

* "OrderedDict"의 "popitem()" 메서드는 서명이 다릅니다. 어떤 항목을 팝
  할지는 지정하는 선택적 인자를 받아들입니다.

  A regular "dict" can emulate OrderedDict's "od.popitem(last=True)"
  with "d.popitem()" which is guaranteed to pop the rightmost (last)
  item.

  A regular "dict" can emulate OrderedDict's "od.popitem(last=False)"
  with "(k := next(iter(d)), d.pop(k))" which will return and remove
  the leftmost (first) item if it exists.

* "OrderedDict"에는 요소를 효율적으로 끝으로 재배치하는
  "move_to_end()" 메서드가 있습니다.

  A regular "dict" can emulate OrderedDict's "od.move_to_end(k,
  last=True)" with "d[k] = d.pop(k)" which will move the key and its
  associated value to the rightmost (last) position.

  A regular "dict" does not have an efficient equivalent for
  OrderedDict's "od.move_to_end(k, last=False)" which moves the key
  and its associated value to the leftmost (first) position.

* 파이썬 3.8 이전에는, "dict"에 "__reversed__()" 메서드가 없었습니다.

class collections.OrderedDict([items])

   딕셔너리 순서 재배치에 특화된 메서드가 있는 "dict" 서브 클래스의 인
   스턴스를 반환합니다.

   버전 3.1에 추가.

   popitem(last=True)

      순서 있는 딕셔너리의 "popitem()" 메서드는 (키, 값) 쌍을 반환하고
      제거합니다. *last*가 참이면 쌍이 LIFO (last-in, first-out - 후입
      선출) 순서로 반환되고, 거짓이면 FIFO (first-in, first-out - 선입
      선출) 순서로 반환됩니다.

   move_to_end(key, last=True)

      Move an existing *key* to either end of an ordered dictionary.
      The item is moved to the right end if *last* is true (the
      default) or to the beginning if *last* is false.  Raises
      "KeyError" if the *key* does not exist:

         >>> d = OrderedDict.fromkeys('abcde')
         >>> d.move_to_end('b')
         >>> ''.join(d)
         'acdeb'
         >>> d.move_to_end('b', last=False)
         >>> ''.join(d)
         'bacde'

      버전 3.2에 추가.

일반적인 매핑 메서드 외에도 순서 있는 딕셔너리는 "reversed()"를 사용하
는 역 이터레이션을 지원합니다.

"OrderedDict" 객체 간의 동등성(equality) 테스트는 순서를 고려하며
"list(od1.items())==list(od2.items())"로 구현됩니다. "OrderedDict" 객
체와 다른 "Mapping" 객체 간의 동등성 테스트는 일반 딕셔너리처럼 순서를
고려하지 않습니다. 이 때문에 "OrderedDict" 객체를 일반 딕셔너리가 사용
되는 모든 곳에 대체 할 수 있습니다.

버전 3.5에서 변경: "OrderedDict"의 items, keys 및 values *뷰*는 이제
"reversed()"를 사용하는 역 이터레이션을 지원합니다.

버전 3.6에서 변경: **PEP 468**을 수락함에 따라, "OrderedDict" 생성자와
"update()" 메서드로 전달된 키워드 인자의 순서가 보존됩니다.

버전 3.9에서 변경: **PEP 584**에 지정된, 병합("|")과 업데이트("|=") 연
산자가 추가되었습니다.


"OrderedDict" 예제와 조리법
---------------------------

키가 *마지막에* 삽입된 순서를 기억하는 순서 있는 딕셔너리 변형을 만드
는 것은 간단합니다. 새 항목이 기존 항목을 덮어쓰면, 원래 삽입 위치가
변경되고 끝으로 이동합니다:

   class LastUpdatedOrderedDict(OrderedDict):
       'Store items in the order the keys were last added'

       def __setitem__(self, key, value):
           super().__setitem__(key, value)
           self.move_to_end(key)

An "OrderedDict" would also be useful for implementing variants of
"functools.lru_cache()":

   from time import time

   class TimeBoundedLRU:
       "LRU Cache that invalidates and refreshes old entries."

       def __init__(self, func, maxsize=128, maxage=30):
           self.cache = OrderedDict()      # { args : (timestamp, result)}
           self.func = func
           self.maxsize = maxsize
           self.maxage = maxage

       def __call__(self, *args):
           if args in self.cache:
               self.cache.move_to_end(args)
               timestamp, result = self.cache[args]
               if time() - timestamp <= self.maxage:
                   return result
           result = self.func(*args)
           self.cache[args] = time(), result
           if len(self.cache) > self.maxsize:
               self.cache.popitem(0)
           return result

   class MultiHitLRUCache:
       """ LRU cache that defers caching a result until
           it has been requested multiple times.

           To avoid flushing the LRU cache with one-time requests,
           we don't cache until a request has been made more than once.

       """

       def __init__(self, func, maxsize=128, maxrequests=4096, cache_after=1):
           self.requests = OrderedDict()   # { uncached_key : request_count }
           self.cache = OrderedDict()      # { cached_key : function_result }
           self.func = func
           self.maxrequests = maxrequests  # max number of uncached requests
           self.maxsize = maxsize          # max number of stored return values
           self.cache_after = cache_after

       def __call__(self, *args):
           if args in self.cache:
               self.cache.move_to_end(args)
               return self.cache[args]
           result = self.func(*args)
           self.requests[args] = self.requests.get(args, 0) + 1
           if self.requests[args] <= self.cache_after:
               self.requests.move_to_end(args)
               if len(self.requests) > self.maxrequests:
                   self.requests.popitem(0)
           else:
               self.requests.pop(args, None)
               self.cache[args] = result
               if len(self.cache) > self.maxsize:
                   self.cache.popitem(0)
           return result


"UserDict" 객체
===============

"UserDict" 클래스는 딕셔너리 객체를 감싸는 래퍼 역할을 합니다. 이 클래
스의 필요성은 "dict"에서 직접 서브 클래싱 할 수 있는 능력에 의해 부분
적으로 대체되었습니다; 그러나 하부 딕셔너리를 어트리뷰트로 액세스 할
수 있어서, 이 클래스를 사용하면 작업하기가 더 쉬울 수 있습니다.

class collections.UserDict([initialdata])

   Class that simulates a dictionary.  The instance's contents are
   kept in a regular dictionary, which is accessible via the "data"
   attribute of "UserDict" instances.  If *initialdata* is provided,
   "data" is initialized with its contents; note that a reference to
   *initialdata* will not be kept, allowing it to be used for other
   purposes.

   "UserDict" 인스턴스는 매핑의 메서드와 연산을 지원할 뿐만 아니라, 다
   음과 같은 어트리뷰트를 제공합니다:

   data

      "UserDict" 클래스의 내용을 저장하는 데 사용되는 실제 딕셔너리.


"UserList" 객체
===============

이 클래스는 리스트 객체를 둘러싸는 래퍼 역할을 합니다. 여러분 자신의
리스트류 클래스가 상속하고 기존 메서드를 재정의하거나 새로운 메서드를
추가할 수 있는 유용한 베이스 클래스입니다. 이런 식으로 리스트에 새로운
동작을 추가 할 수 있습니다.

이 클래스의 필요성은 "list"에서 직접 서브 클래싱할 수 있는 능력에 의해
부분적으로 대체되었습니다; 그러나 하부 리스트에 어트리뷰트로 액세스할
수 있어서, 이 클래스를 사용하면 작업하기가 더 쉬울 수 있습니다.

class collections.UserList([list])

   리스트를 시뮬레이트 하는 클래스. 인스턴스의 내용은 일반 리스트로 유
   지되며 "UserList" 인스턴스의 "data" 어트리뷰트를 통해 액세스 할 수
   있습니다. 인스턴스의 내용은 초기에 *list*의 사본으로 설정되며, 기본
   값은 빈 목록 "[]"입니다. *list*는 모든 이터러블일 수 있습니다, 예를
   들어 실제 파이썬 리스트나 "UserList" 객체.

   "UserList" 인스턴스는 가변 시퀀스의 메서드와 연산을 지원할 뿐만 아
   니라 다음 어트리뷰트를 제공합니다:

   data

      "UserList" 클래스의 내용을 저장하는 데 사용되는 실제 "list" 객체
      .

**서브 클래싱 요구 사항:** "UserList"의 서브 클래스는 인자가 없거나 하
나의 인자로 호출 할 수 있는 생성자를 제공해야 합니다. 새 시퀀스를 반환
하는 리스트 연산은 실제 구현 클래스의 인스턴스를 만들려고 시도합니다.
이를 위해, 데이터 소스로 사용되는 시퀀스 객체인 단일 매개 변수로 생성
자를 호출할 수 있다고 가정합니다.

파생 클래스가 이 요구 사항을 준수하고 싶지 않다면, 이 클래스에서 지원
하는 모든 특수 메서드를 재정의해야 합니다; 이때 제공해야 하는 메서드에
대한 정보는 소스를 참조하십시오.


"UserString" 객체
=================

"UserString" 클래스는 문자열 객체를 둘러싸는 래퍼 역할을 합니다. 이 클
래스의 필요성은 "str"에서 직접 서브 클래싱할 수 있는 능력에 의해 부분
적으로 대체되었습니다; 그러나 하부 문자열을 어트리뷰트로 액세스할 수
있어서, 이 클래스를 사용하면 작업하기가 더 쉬울 수 있습니다.

class collections.UserString(seq)

   문자열 객체를 시뮬레이트 하는 클래스. 인스턴스의 내용은 일반 문자열
   객체로 유지되며, "UserString" 인스턴스의 "data" 어트리뷰트를 통해
   액세스 할 수 있습니다. 인스턴스의 내용은 처음에 *seq*의 사본으로 설
   정됩니다. *seq* 인자는 내장 "str()" 함수를 사용하여 문자열로 변환
   할 수 있는 모든 객체가 될 수 있습니다.

   "UserString" 인스턴스는 문자열의 메서드와 연산을 지원할 뿐만 아니라
   다음과 같은 어트리뷰트를 제공합니다:

   data

      "UserString" 클래스의 내용을 저장하는 데 사용되는 실제 "str" 객
      체.

   버전 3.5에서 변경: 새로운 메서드 "__getnewargs__", "__rmod__",
   "casefold", "format_map", "isprintable" 및 "maketrans".
