collections — 컨테이너 데이터형

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


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

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에 지정된, ||= 연산자에 대한 지원이 추가되었습니다.

더 보기

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을 지정하지 않으면, 새 데크는 비어 있습니다.

Deques are a generalization of stacks and queues (the name is pronounced “deck” and is short for “double-ended queue”). Deques support thread-safe, memory efficient appends and pops from either side of the deque with approximately the same O(1) performance in either direction.

Though list objects support similar operations, they are optimized for fast fixed-length operations and incur O(n) memory movement costs for pop(0) and insert(0, v) operations which change both the size and position of the underlying data representation.

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에 추가.

In addition to the above, deques support iteration, pickling, len(d), reversed(d), copy.copy(d), copy.deepcopy(d), membership testing with the in operator, and subscript references such as d[0] to access the first element. Indexed access is O(1) at both ends but slows to O(n) in the middle. For fast random access, use lists instead.

버전 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, rotroll과 같은 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_factoryNone이 아니면, 주어진 key에 대한 기본값을 제공하기 위해 인자 없이 호출되며, 반환 값은 key로 딕셔너리에 삽입되고 반환됩니다.

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

This method is called by the __getitem__() method of the dict class when the requested key is not found; whatever it returns or raises is then returned or raised by __getitem__().

Note that __missing__() is not called for any operations besides __getitem__(). This means that get() will, like normal dictionaries, return None as a default rather than using default_factory.

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

default_factory

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

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

defaultdict

listdefault_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_factoryint로 설정하면 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_factoryset으로 설정하면, 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를 제거합니다.

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

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

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

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

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

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

버전 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)

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

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)).

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

    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 순서로 반환되고, 거짓이면 FIFO 순서로 반환됩니다.

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 collections import OrderedDict
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, isprintablemaketrans.