コレクション—コンテナデータ型—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.8/library/collections
移動先:案内検索

collections —コンテナのデータ型

ソースコード: :source: `Lib / collections / __ init __。py`



このモジュールは、Pythonの汎用組み込みコンテナー dictlistset 、および tuple の代替を提供する特殊なコンテナーデータ型を実装します。

namedtuple() 名前付きフィールドを持つタプルサブクラスを作成するためのファクトリ関数
deque 両端に高速な追加とポップを備えたリストのようなコンテナ
ChainMap 複数のマッピングの単一のビューを作成するためのdictのようなクラス
Counter ハッシュ可能なオブジェクトをカウントするためのdictサブクラス
OrderedDict 注文エントリが追加されたことを記憶するdictサブクラス
defaultdict 欠落値を提供するためにファクトリ関数を呼び出すdictサブクラス
UserDict dictサブクラス化を容易にするための辞書オブジェクトのラッパー
UserList リストのサブクラス化を容易にするためのリストオブジェクトのラッパー
UserString 文字列のサブクラス化を容易にするための文字列オブジェクトのラッパー

ChainMap オブジェクト

バージョン3.3の新機能。


ChainMap クラスは、多数のマッピングをすばやくリンクして、単一のユニットとして扱うことができるようにするために提供されています。 多くの場合、新しい辞書を作成して複数の update()呼び出しを実行するよりもはるかに高速です。

このクラスは、ネストされたスコープをシミュレートするために使用でき、テンプレート作成に役立ちます。

class collections.ChainMap(*maps)

ChainMap は、複数のdictまたは他のマッピングをグループ化して、単一の更新可能なビューを作成します。 maps が指定されていない場合、新しいチェーンが常に少なくとも1つのマッピングを持つように、単一の空のディクショナリが提供されます。

基になるマッピングはリストに保存されます。 そのリストは公開されており、 maps 属性を使用してアクセスまたは更新できます。 他の状態はありません。

ルックアップは、キーが見つかるまで、基になるマッピングを連続して検索します。 対照的に、書き込み、更新、および削除は、最初のマッピングでのみ機能します。

ChainMap は、参照によって基礎となるマッピングを組み込んでいます。 したがって、基になるマッピングの1つが更新されると、それらの変更は ChainMap に反映されます。

通常の辞書メソッドはすべてサポートされています。 さらに、 maps 属性、新しいサブコンテキストを作成するためのメソッド、および最初のマッピングを除くすべてにアクセスするためのプロパティがあります。

maps

ユーザーが更新可能なマッピングのリスト。 リストは、最初に検索されたものから最後に検索されたものの順に並べられています。 これは唯一の保存された状態であり、検索するマッピングを変更するために変更できます。 リストには常に少なくとも1つのマッピングが含まれている必要があります。

new_child(m=None)

新しいマップとそれに続く現在のインスタンスのすべてのマップを含む新しい ChainMap を返します。 mを指定すると、マッピングリストの先頭にある新しいマップになります。 指定しない場合、空のdictが使用されるため、d.new_child()の呼び出しはChainMap({}, *d.maps)と同等です。 このメソッドは、親マッピングの値を変更せずに更新できるサブコンテキストを作成するために使用されます。

バージョン3.4で変更:オプションのmパラメーターが追加されました。

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']

も参照してください


ChainMap の例とレシピ

このセクションでは、チェーンマップを操作するためのさまざまなアプローチを示します。

Pythonの内部ルックアップチェーンをシミュレートする例:

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'})

カウンターオブジェクト

便利で迅速な集計をサポートするためのカウンターツールが用意されています。 例えば:

>>> # 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])

Counter は、ハッシュ可能なオブジェクトをカウントするための dict サブクラスです。 これは、要素がディクショナリキーとして格納され、それらのカウントがディクショナリ値として格納されるコレクションです。 カウントは、ゼロまたは負のカウントを含む任意の整数値にすることができます。 Counter クラスは、他の言語のバッグまたはマルチセットに似ています。

要素は iterable からカウントされるか、別のマッピング(またはカウンター)から初期化されます。

>>> 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 を発生させる代わりに、欠落しているアイテムに対してゼロカウントを返すことを除いて、ディクショナリインターフェイスがあります。

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

カウントをゼロに設定しても、要素はカウンターから削除されません。 delを使用して、完全に削除します。

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

バージョン3.1の新機能。

バージョン3.7で変更: dict サブクラスとして、 Counter 挿入順序を記憶する機能を継承しました。 Counter オブジェクトの数学演算も順序を保持します。 結果は、要素が最初に左側のオペランドで検出されたとき、次に右側のオペランドで検出された順序に従って順序付けられます。

カウンターオブジェクトは、すべてのディクショナリで使用可能なメソッド以外に、次の3つのメソッドをサポートします。

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()はカウンター内の all 要素を返します。 カウントが等しい要素は、最初に検出された順序で並べられます。

>>> Counter('abracadabra').most_common(3)
[('a', 5), ('b', 2), ('r', 2)]
subtract([iterable-or-mapping])

要素は、 iterable または別の mapping (またはカウンター)から減算されます。 dict.update()と同様ですが、カウントを置き換えるのではなく減算します。 入力と出力の両方がゼロまたは負の場合があります。

>>> 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の新機能。

通常のディクショナリメソッドは、 Counter オブジェクトで使用できますが、2つはカウンターで異なる動作をします。

fromkeys(iterable)

このクラスメソッドは、 Counter オブジェクトには実装されていません。

update([iterable-or-mapping])

要素は、 iterable からカウントされるか、別のマッピング(またはカウンター)から追加されます。 dict.update()と同様ですが、カウントを置き換える代わりに追加します。 また、 iterable は、(key, value)ペアのシーケンスではなく、要素のシーケンスであることが期待されます。

Counter オブジェクトを操作するための一般的なパターン:

sum(c.values())                 # 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

Counter オブジェクトを組み合わせてマルチセット(カウントがゼロより大きいカウンター)を生成するために、いくつかの数学演算が提供されています。 加算と減算は、対応する要素のカウントを加算または減算することによってカウンターを結合します。 共通部分と和集合は、対応するカウントの最小値と最大値を返します。 各操作は、符号付きカウントの入力を受け入れることができますが、出力は、カウントが0以下の結果を除外します。

>>> 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 = Counter(a=2, b=-4)
>>> +c
Counter({'a': 2})
>>> -c
Counter({'b': 4})

バージョン3.3の新機能:単項プラス、単項マイナス、およびインプレース多重集合演算のサポートが追加されました。


ノート

カウンターは主に、実行中のカウントを表すために正の整数で機能するように設計されました。 ただし、他のタイプまたは負の値を必要とするユースケースを不必要に排除しないように注意が払われました。 これらのユースケースを支援するために、このセクションでは最小範囲とタイプの制限について説明します。

  • Counter クラス自体は、キーと値に制限のない辞書サブクラスです。 値はカウントを表す数値であることが意図されていますが、値フィールドに何かをできます
  • most_common()メソッドでは、値が順序付け可能である必要があるだけです。
  • c[key] += 1などのインプレース演算の場合、値型は加算と減算のみをサポートする必要があります。 したがって、分数、浮動小数点数、および小数が機能し、負の値がサポートされます。 同じことが update()extract()にも当てはまり、入力と出力の両方に負の値とゼロの値を許可します。
  • マルチセットメソッドは、正の値を持つユースケース専用に設計されています。 入力は負またはゼロの場合がありますが、正の値の出力のみが作成されます。 タイプの制限はありませんが、値タイプは加算、減算、および比較をサポートする必要があります。
  • elements()メソッドには整数カウントが必要です。 ゼロカウントと負のカウントは無視されます。


も参照してください

  • Smalltalkのバッグクラス

  • マルチセットのウィキペディアエントリ。

  • C ++マルチセットチュートリアルと例。

  • マルチセットの数学演算とその使用例については、を参照してください。 クヌース、ドナルド。 Art of Computer Programming Volume II、セクション4.6.3、演習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は、スタックとキューを一般化したものです(名前は「deck」と発音され、「両端キュー」の略です)。 Dequeは、スレッドセーフでメモリ効率の高い追加と、Dequeの両側からのポップをサポートし、どちらの方向でもほぼ同じO(1)パフォーマンスを実現します。

list オブジェクトは同様の操作をサポートしますが、高速の固定長操作用に最適化されており、pop(0)およびinsert(0, v)操作の両方を変更するO(n)メモリ移動コストが発生します。基になるデータ表現のサイズと位置。

maxlen が指定されていないか、Noneの場合、両端キューは任意の長さに拡大する可能性があります。 それ以外の場合、両端キューは指定された最大長に制限されます。 制限された長さの両端キューがいっぱいになると、新しいアイテムが追加されると、対応する数のアイテムが反対側から破棄されます。 有界長の両端キューは、Unixのtailフィルターと同様の機能を提供します。 また、最新のアクティビティのみが対象となるトランザクションやその他のデータプールを追跡する場合にも役立ちます。

Dequeオブジェクトは、次のメソッドをサポートします。

append(x)

x を両端キューの右側に追加します。

appendleft(x)

x を両端キューの左側に追加します。

clear()

dequeからすべての要素を削除し、長さ0のままにします。

copy()

dequeの浅いコピーを作成します。

バージョン3.5の新機能。

count(x)

x に等しい両端キュー要素の数を数えます。

バージョン3.2の新機能。

extend(iterable)

iterable引数から要素を追加して、両端キューの右側を拡張します。

extendleft(iterable)

iterable の要素を追加して、両端キューの左側を拡張します。 一連の左追加により、反復可能な引数の要素の順序が逆になることに注意してください。

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

deque内の x の位置を返します(インデックス start 以降、インデックス stop の前)。 最初の一致を返すか、見つからない場合は ValueError を発生させます。

バージョン3.5の新機能。

insert(i, x)

xi の位置の両端キューに挿入します。

挿入によって有界両端キューが maxlen を超えて大きくなる場合、 IndexError が発生します。

バージョン3.5の新機能。

pop()

dequeの右側から要素を削除して返します。 要素が存在しない場合、 IndexError が発生します。

popleft()

dequeの左側から要素を削除して返します。 要素が存在しない場合、 IndexError が発生します。

remove(value)

value の最初の出現を削除します。 見つからない場合は、 ValueError を発生させます。

reverse()

dequeの要素をインプレースで反転してから、Noneを返します。

バージョン3.2の新機能。

rotate(n=1)

deque n ステップを右に回転させます。 n が負の場合は、左に回転します。

dequeが空でない場合、右に1ステップ回転するとd.appendleft(d.pop())に相当し、左に1ステップ回転するとd.append(d.popleft())に相当します。

Dequeオブジェクトは、1つの読み取り専用属性も提供します。

maxlen

dequeの最大サイズまたは無制限の場合は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 レシピ

このセクションでは、両端キューを操作するためのさまざまなアプローチを示します。

有界長の両端キューは、Unixのtailフィルターと同様の機能を提供します。

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

dequesを使用する別のアプローチは、右に追加して左にポップすることにより、最近追加された要素のシーケンスを維持することです。

def moving_average(iterable, n=3):
    # moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0
    # http://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

ラウンドロビンスケジューラは、 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]の純粋なPython実装は、rotate()メソッドに依存して、ポップされる要素を配置します。

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

deque スライスを実装するには、 rotate()を適用する同様のアプローチを使用して、ターゲット要素をdequeの左側に移動します。 popleft()を使用して古いエントリを削除し、 extends()を使用して新しいエントリを追加してから、回転を逆にします。 そのアプローチのマイナーなバリエーションで、dupdropswapover、 [などのForthスタイルのスタック操作を簡単に実装できます。 X152X]、rot、およびroll


defaultdict オブジェクト

class collections.defaultdict([default_factory[, ...]])

新しい辞書のようなオブジェクトを返します。 defaultdict は、組み込みの dict クラスのサブクラスです。 1つのメソッドをオーバーライドし、1つの書き込み可能なインスタンス変数を追加します。 残りの機能は dict クラスの場合と同じであり、ここでは説明していません。

最初の引数は、 default_factory 属性の初期値を提供します。 デフォルトはNoneです。 残りのすべての引数は、キーワード引数を含め、 dict コンストラクターに渡された場合と同じように扱われます。

defaultdict オブジェクトは、標準の dict 操作に加えて、次のメソッドをサポートします。

__missing__(key)

default_factory 属性がNoneの場合、 key を引数として KeyError 例外が発生します。

default_factoryNoneでない場合、指定されたキーのデフォルト値を提供するために引数なしで呼び出され、この値はの辞書に挿入されます。 key 、および返されます。

default_factory を呼び出すと例外が発生した場合、この例外は変更されずに伝播されます。

このメソッドは、要求されたキーが見つからない場合、 dict クラスの__getitem__()メソッドによって呼び出されます。 返されるか発生するものはすべて、__getitem__()によって返されるか発生します。

__ missing __()は、__getitem__()以外の操作では呼び出されないことに注意してください。 つまり、get()は、通常の辞書と同様に、 default_factory を使用するのではなく、Noneをデフォルトとして返します。

defaultdict オブジェクトは、次のインスタンス変数をサポートします。

default_factory

この属性は、 __ missing __()メソッドによって使用されます。 最初の引数からコンストラクター(存在する場合)またはNone(存在しない場合)に初期化されます。

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.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 がカウントに役立ちます(他の言語のバッグやマルチセットなど)。

>>> 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を提供します。 次に、インクリメント操作により、各文字のカウントが増加します。

常にゼロを返す関数 int()は、定数関数の特殊なケースです。 定数関数を作成するためのより高速で柔軟な方法は、(ゼロだけでなく)任意の定数値を提供できるラムダ関数を使用することです。

>>> 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 という名前の新しいタプルサブクラスを返します。 新しいサブクラスは、属性ルックアップによってアクセス可能なフィールドを持ち、インデックス付けと反復が可能なタプルのようなオブジェクトを作成するために使用されます。 サブクラスのインスタンスには、便利なdocstring(typenameとfield_namesを含む)と、タプルの内容をname=value形式でリストする便利な__repr__()メソッドもあります。

field_names は、['x', 'y']などの文字列のシーケンスです。 または、 field_names は、'x y''x, y'のように、各フィールド名を空白やコンマで区切った単一の文字列にすることができます。

アンダースコアで始まる名前を除いて、任意の有効なPython識別子をフィールド名に使用できます。 有効な識別子は文字、数字、およびアンダースコアで構成されますが、数字またはアンダースコアで始まらず、クラスforなどのキーワードにすることはできません。 ] returnglobalpass 、または raise

rename がtrueの場合、無効なフィールド名は自動的に位置名に置き換えられます。 たとえば、['abc', 'def', 'ghi', 'abc']['abc', '_1', 'ghi', '_3']に変換され、キーワードdefと重複するフィールド名abcが削除されます。

defaults は、デフォルト値のNoneまたは iterable にすることができます。 デフォルト値のあるフィールドは、デフォルト値のないフィールドの後に来る必要があるため、 defaults が右端のパラメーターに適用されます。 たとえば、フィールド名が['x', 'y', 'z']で、デフォルトが(1, 2)の場合、xは必須の引数になり、yはデフォルトで [になります。 X151X]、およびzはデフォルトで2になります。

module が定義されている場合、指定されたタプルの__module__属性はその値に設定されます。

名前付きタプルインスタンスにはインスタンスごとの辞書がないため、軽量であり、通常のタプルよりも多くのメモリを必要としません。

バージョン3.1で変更: 名前の変更のサポートが追加されました。

バージョン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)

タプルから継承されたメソッドに加えて、名前付きタプルは3つの追加メソッドと2つの属性をサポートします。 フィールド名との競合を防ぐために、メソッド名と属性名はアンダースコアで始まります。

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 を返します。 Python 3.7以降、通常のdictが順序付けられることが保証されています。 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

辞書を名前付きタプルに変換するには、double-star-operatorを使用します(引数リストの解凍で説明されています)。

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

名前付きタプルは通常のPythonクラスであるため、サブクラスを使用して機能を簡単に追加または変更できます。 計算フィールドと固定幅の印刷形式を追加する方法は次のとおりです。

>>> 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',))

Docstringは、__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で変更:プロパティdocstringが書き込み可能になりました。


も参照してください

  • 名前付きタプルのタイプヒントを追加する方法については、 typing.NamedTuple を参照してください。 また、 class キーワードを使用したエレガントな表記も提供します。

    class Component(NamedTuple):
        part_number: int
        weight: float
        description: Optional[str] = None
  • タプルではなく基になるディクショナリに基づく変更可能な名前空間については、 types.SimpleNamespace()を参照してください。

  • dataclasses モジュールは、生成された特別なメソッドをユーザー定義クラスに自動的に追加するためのデコレーターと関数を提供します。


OrderedDict オブジェクト

順序付き辞書は通常の辞書と同じですが、順序付け操作に関連するいくつかの追加機能があります。 組み込みの dict クラスが挿入順序を記憶できるようになったため、これらの重要性は低くなりました(この新しい動作は、Python 3.7で保証されるようになりました)。

dict とのいくつかの違いはまだ残っています。

  • 通常の dict は、マッピング操作に非常に優れているように設計されています。 挿入順序の追跡は二次的なものでした。
  • OrderedDict は、操作の並べ替えに適した設計になっています。 スペース効率、反復速度、および更新操作のパフォーマンスは二次的なものでした。
  • アルゴリズム的には、 OrderedDict は、 dict よりも頻繁な並べ替え操作をより適切に処理できます。 これにより、最近のアクセスの追跡に適しています(たとえば、 LRUキャッシュ内)。
  • OrderedDict の等価演算は、一致する順序をチェックします。
  • OrderedDictpopitem()メソッドの署名は異なります。 ポップするアイテムを指定するオプションの引数を受け入れます。
  • OrderedDict には、要素をエンドポイントに効率的に再配置するためのmove_to_end()メソッドがあります。
  • Python 3.8まで、 dict には__reversed__()メソッドがありませんでした。
class collections.OrderedDict([items])

辞書式順序の再配置に特化したメソッドを持つ dict サブクラスのインスタンスを返します。

バージョン3.1の新機能。

popitem(last=True)

順序付けされた辞書の popitem()メソッドは、(キー、値)ペアを返したり削除したりします。 ペアは、 last がtrueの場合は LIFO の順序で返され、falseの場合は FIFO の順序で返されます。

move_to_end(key, last=True)

既存のキーを順序付けられた辞書の両端に移動します。 last がtrue(デフォルト)の場合は右端に移動し、 last がfalseの場合は先頭に移動します。 key が存在しない場合、 KeyError を発生させます。

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

バージョン3.2の新機能。

通常のマッピング方法に加えて、順序付けされた辞書は、 reverse()を使用した逆反復もサポートします。

OrderedDict オブジェクト間の同等性テストは順序に依存し、list(od1.items())==list(od2.items())として実装されます。 OrderedDict オブジェクトと他の Mapping オブジェクト間の同等性テストは、通常の辞書のように順序に依存しません。 これにより、 OrderedDict オブジェクトを、通常の辞書が使用されている場所ならどこでも置き換えることができます。

バージョン3.5で変更: OrderedDict のアイテム、キー、および値ビューは、 reverse()を使用した逆反復をサポートするようになりました。


バージョン3.6で変更: PEP 468 の受け入れにより、 OrderedDict コンストラクターとその[ X178X] メソッド。


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)

OrderedDict は、 functools.lru_cache()のバリアントを実装する場合にも役立ちます。

class LRU(OrderedDict):
    'Limit size, evicting the least recently looked-up key when full'

    def __init__(self, maxsize=128, /, *args, **kwds):
        self.maxsize = maxsize
        super().__init__(*args, **kwds)

    def __getitem__(self, key):
        value = super().__getitem__(key)
        self.move_to_end(key)
        return value

    def __setitem__(self, key, value):
        if key in self:
            self.move_to_end(key)
        super().__setitem__(key, value)
        if len(self) > self.maxsize:
            oldest = next(iter(self))
            del self[oldest]

UserDict オブジェクト

クラス UserDict は、ディクショナリオブジェクトのラッパーとして機能します。 このクラスの必要性は、 dict から直接サブクラス化する機能に部分的に取って代わられました。 ただし、基になるディクショナリに属性としてアクセスできるため、このクラスの操作は簡単です。

class collections.UserDict([initialdata])

辞書をシミュレートするクラス。 インスタンスのコンテンツは通常の辞書に保存されており、 UserDict インスタンスの data 属性を介してアクセスできます。 initialdata が指定されている場合、 data はその内容で初期化されます。 initialdata への参照は保持されないため、他の目的に使用できることに注意してください。

UserDict インスタンスは、マッピングのメソッドと操作をサポートすることに加えて、次の属性を提供します。

data

UserDict クラスの内容を格納するために使用される実際の辞書。


UserList オブジェクト

このクラスは、リストオブジェクトのラッパーとして機能します。 これは、リストから継承して既存のメソッドをオーバーライドしたり、新しいメソッドを追加したりできる、独自のリストのようなクラスの便利な基本クラスです。 このようにして、リストに新しい動作を追加できます。

このクラスの必要性は、リストから直接サブクラス化する機能に部分的に取って代わられました。 ただし、基になるリストに属性としてアクセスできるため、このクラスの操作は簡単です。

class collections.UserList([list])

リストをシミュレートするクラス。 インスタンスのコンテンツは通常のリストに保持され、 UserList インスタンスの data 属性を介してアクセスできます。 インスタンスのコンテンツは、最初は list のコピーに設定され、デフォルトでは空のリスト[]に設定されます。 list は、実際のPythonリストや UserList オブジェクトなど、任意の反復可能にすることができます。

UserList インスタンスは、可変シーケンスのメソッドと操作をサポートすることに加えて、次の属性を提供します。

data

UserList クラスのコンテンツを格納するために使用される実際の list オブジェクト。

サブクラス化の要件: UserList のサブクラスは、引数なしまたは1つの引数で呼び出すことができるコンストラクターを提供することが期待されています。 新しいシーケンスを返すリスト操作は、実際の実装クラスのインスタンスを作成しようとします。 そのために、コンストラクターは、データソースとして使用されるシーケンスオブジェクトである単一のパラメーターで呼び出すことができると想定しています。

派生クラスがこの要件に準拠することを望まない場合は、このクラスでサポートされているすべての特別なメソッドをオーバーライドする必要があります。 その場合に提供する必要のある方法については、情報源を参照してください。


UserString オブジェクト

クラス UserString は、文字列オブジェクトのラッパーとして機能します。 このクラスの必要性は、 str から直接サブクラス化する機能に部分的に取って代わられました。 ただし、基になる文字列に属性としてアクセスできるため、このクラスの操作は簡単です。

class collections.UserString(seq)

文字列オブジェクトをシミュレートするクラス。 インスタンスのコンテンツは、 UserString インスタンスの data 属性を介してアクセスできる通常の文字列オブジェクトに保持されます。 インスタンスのコンテンツは、最初は seq のコピーに設定されています。 seq 引数は、組み込みの str()関数を使用して文字列に変換できる任意のオブジェクトにすることができます。

文字列のメソッドと操作をサポートすることに加えて、 UserString インスタンスは次の属性を提供します。

data

UserString クラスのコンテンツを格納するために使用される実際の str オブジェクト。

バージョン3.5で変更:新しいメソッド__getnewargs____rmod__casefoldformat_mapisprintable、および[ X104X] 。