8.3. コレクション—高性能コンテナデータ型—Pythonドキュメント

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

8.3。 コレクション —高性能コンテナデータ型

バージョン2.4の新機能。


ソースコード: :source: `Lib / collections.py` and :source: `Lib / _abcoll.py`



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

namedtuple() 名前付きフィールドを持つタプルサブクラスを作成するためのファクトリ関数

バージョン2.6の新機能。


deque 両端に高速な追加とポップを備えたリストのようなコンテナ

バージョン2.4の新機能。


Counter ハッシュ可能なオブジェクトをカウントするためのdictサブクラス

バージョン2.7の新機能。


OrderedDict 注文エントリが追加されたことを記憶するdictサブクラス

バージョン2.7の新機能。


defaultdict 欠落値を提供するためにファクトリ関数を呼び出すdictサブクラス

バージョン2.5の新機能。


具象コンテナクラスに加えて、コレクションモジュールは抽象基本クラスを提供します。これを使用して、クラスが特定のインターフェイスを提供するかどうか、たとえば、ハッシュ可能かマッピングかをテストできます。

8.3.1。 カウンターオブジェクト

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

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

バージョン2.7の新機能。

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

elements()

それぞれをそのカウントと同じ回数繰り返す要素に対してイテレータを返します。 要素は任意の順序で返されます。 要素の数が1未満の場合、 elements()はそれを無視します。

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

n の最も一般的な要素とその数のリストを最も一般的なものから最も少ないものへと返します。 n を省略した場合、またはNoneの場合、 most_common()はカウンター内のすべての要素を返します。 カウントが等しい要素は任意に順序付けられます。

>>> Counter('abracadabra').most_common(3)
[('a', 5), ('r', 2), ('b', 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})

通常のディクショナリメソッドは、 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 += Counter()                  # 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})

ノート

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

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


も参照してください

  • カウンタークラスはPython2.5に適合し、初期のバッグレシピはPython2.4に適合しました。

  • 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


8.3.2。 deque オブジェクト

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

iterable からのデータを使用して( append()を使用して)左から右に初期化された新しいdequeオブジェクトを返します。 iterable が指定されていない場合、新しい両端キューは空です。

Dequesは、スタックとキューを一般化したものです(名前は「deck」と発音され、「両端キュー」の略です)。 Dequeは、スレッドセーフでメモリ効率の高い追加と、Dequeの両側からのポップをサポートし、どちらの方向でもほぼ同じO(1)パフォーマンスを実現します。

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

バージョン2.4の新機能。

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

バージョン2.6で変更: maxlen パラメーターが追加されました。

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

append(x)

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

appendleft(x)

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

clear()

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

count(x)

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

バージョン2.7の新機能。

extend(iterable)

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

extendleft(iterable)

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

pop()

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

popleft()

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

remove(value)

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

バージョン2.5の新機能。

reverse()

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

バージョン2.7の新機能。

rotate(n=1)

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

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

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

maxlen

dequeの最大サイズまたは無制限の場合はNone

バージョン2.7の新機能。

上記に加えて、両端キューは、反復、ピクルス、len(d)reversed(d)copy.copy(d)copy.deepcopy(d)in を使用したメンバーシップテストをサポートします。 ]演算子、およびd[-1]などの添え字参照。 インデックス付きアクセスは、両端がO(1)ですが、中央がO(n)になります。 高速ランダムアクセスの場合は、代わりにリストを使用してください。

例:

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

8.3.2.1。 deque レシピ

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

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

def tail(filename, n=10):
    'Return the last n lines of a file'
    return deque(open(filename), 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 / float(n)

rotate()メソッドは、 deque のスライスと削除を実装する方法を提供します。 たとえば、del d[n]の純粋なPython実装は、rotate()メソッドに依存して、ポップされる要素を配置します。

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

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


8.3.3。 defaultdict オブジェクト

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

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

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

バージョン2.5の新機能。

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

__missing__(key)

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

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

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

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

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

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

default_factory

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

8.3.3.1。 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)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

各キーが初めて検出されたとき、そのキーはまだマッピングに含まれていません。 したがって、エントリは、空のlistを返すdefault_factory関数を使用して自動的に作成されます。 次に、list.append()操作は、値を新しいリストに添付します。 キーが再び検出されると、ルックアップは正常に進行し(そのキーのリストを返します)、list.append()操作はリストに別の値を追加します。 この手法は、 dict.setdefault()を使用する同等の手法よりも単純で高速です。

>>> d = {}
>>> for k, v in s:
...     d.setdefault(k, []).append(v)
...
>>> 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
...
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]

文字が最初に検出されたとき、その文字はマッピングから欠落しているため、default_factory関数は int()を呼び出して、デフォルトのカウント0を提供します。 次に、インクリメント操作により、各文字のカウントが増加します。

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

>>> def constant_factory(value):
...     return itertools.repeat(value).next
>>> 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)
...
>>> d.items()
[('blue', set([2, 4])), ('red', set([1, 3]))]

8.3.4。 namedtuple() 名前付きフィールドを持つタプルのファクトリ関数

名前付きタプルは、タプル内の各位置に意味を割り当て、より読みやすい自己文書化コードを可能にします。 これらは、通常のタプルが使用されている場所ならどこでも使用でき、位置インデックスの代わりに名前でフィールドにアクセスする機能を追加します。

collections.namedtuple(typename, field_names[, verbose=False][, rename=False])

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

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

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

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

verbose がtrueの場合、クラス定義はビルドされる直前に出力されます。

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

バージョン2.6の新機能。

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

例:

>>> Point = namedtuple('Point', ['x', 'y'], verbose=True)
class Point(tuple):
    'Point(x, y)'

    __slots__ = ()

    _fields = ('x', 'y')

    def __new__(_cls, x, y):
        'Create new instance of Point(x, y)'
        return _tuple.__new__(_cls, (x, y))

    @classmethod
    def _make(cls, iterable, new=tuple.__new__, len=len):
        'Make a new Point object from a sequence or iterable'
        result = new(cls, iterable)
        if len(result) != 2:
            raise TypeError('Expected 2 arguments, got %d' % len(result))
        return result

    def __repr__(self):
        'Return a nicely formatted representation string'
        return 'Point(x=%r, y=%r)' % self

    def _asdict(self):
        'Return a new OrderedDict which maps field names to their values'
        return OrderedDict(zip(self._fields, self))

    def _replace(_self, **kwds):
        'Return a new Point object replacing specified fields with new values'
        result = _self._make(map(kwds.pop, ('x', 'y'), _self))
        if kwds:
            raise ValueError('Got unexpected field names: %r' % kwds.keys())
        return result

    def __getnewargs__(self):
        'Return self as a plain tuple.  Used by copy and pickle.'
        return tuple(self)

    __dict__ = _property(_asdict)

    def __getstate__(self):
        'Exclude the OrderedDict from pickling'
        pass

    x = _property(_itemgetter(0), doc='Alias for field number 0')

    y = _property(_itemgetter(1), doc='Alias for field number 1')



>>> 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つの追加メソッドと1つの属性をサポートします。 フィールド名との競合を防ぐために、メソッド名と属性名はアンダースコアで始まります。

classmethod somenamedtuple._make(iterable)

既存のシーケンスまたは反復可能から新しいインスタンスを作成するクラスメソッド。

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

フィールド名を対応する値にマップする新しい OrderedDict を返します。

>>> p = Point(x=11, y=22)
>>> p._asdict()
OrderedDict([('x', 11), ('y', 22)])

バージョン2.7で変更:通常の dict の代わりに OrderedDict を返します。

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)

名前が文字列に格納されているフィールドを取得するには、 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',))

_replace()を使用してプロトタイプインスタンスをカスタマイズすることにより、デフォルト値を実装できます。

>>> Account = namedtuple('Account', 'owner balance transaction_count')
>>> default_account = Account('<owner name>', 0.0, 0)
>>> johns_account = default_account._replace(owner='John')

列挙型定数は名前付きタプルを使用して実装できますが、単純なクラス宣言を使用する方が簡単で効率的です。

>>> Status = namedtuple('Status', 'open pending closed')._make(range(3))
>>> Status.open, Status.pending, Status.closed
(0, 1, 2)
>>> class Status:
...     open, pending, closed = range(3)

も参照してください

名前付きタプルレシピはPython2.4に適合しています。


8.3.5。 OrderedDict オブジェクト

順序付けられた辞書は通常の辞書と同じですが、アイテムが挿入された順序を覚えています。 順序付けられた辞書を反復処理すると、キーが最初に追加された順序でアイテムが返されます。

class collections.OrderedDict([items])

通常の dict メソッドをサポートするdictサブクラスのインスタンスを返します。 OrderedDict は、キーが最初に挿入された順序を記憶するdictです。 新しいエントリが既存のエントリを上書きする場合、元の挿入位置は変更されません。 エントリを削除して再挿入すると、最後に移動します。

バージョン2.7の新機能。

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

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

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

OrderedDict コンストラクターとupdate()メソッドはどちらもキーワード引数を受け入れますが、Pythonの関数呼び出しセマンティクスが通常の順序付けられていない辞書を使用してキーワード引数を渡すため、順序が失われます。

8.3.5.1。 OrderedDict 例とレシピ

順序付けされた辞書はその挿入順序を記憶しているため、並べ替えと組み合わせて使用して、並べ替えられた辞書を作成できます。

>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}

>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])

新しくソートされた辞書は、エントリが削除されてもソート順を維持します。 ただし、新しいキーが追加されると、キーは最後に追加され、並べ替えは維持されません。

キーが最後に挿入された順序を記憶する順序付き辞書バリアントを作成することも簡単です。 新しいエントリが既存のエントリを上書きする場合、元の挿入位置が変更され、最後に移動されます。

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

    def __setitem__(self, key, value):
        if key in self:
            del self[key]
        OrderedDict.__setitem__(self, key, value)

順序付けされた辞書を Counter クラスと組み合わせて、カウンターが順序要素が最初に検出されたことを記憶するようにすることができます。

class OrderedCounter(Counter, OrderedDict):
     'Counter that remembers the order elements are first encountered'

     def __repr__(self):
         return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))

     def __reduce__(self):
         return self.__class__, (OrderedDict(self),)

8.3.6。 コレクション抽象基本クラス

コレクションモジュールは、次の ABC を提供します。

ABC から継承 抽象メソッド Mixinメソッド
Container __contains__
Hashable __hash__
Iterable __iter__
Iterator Iterable next __iter__
Sized __len__
Callable __call__
Sequence サイズ反復可能コンテナ __getitem____len__ __contains____iter____reversed__index、およびcount
MutableSequence Sequence __getitem____setitem____delitem____len__insert 継承された Sequence メソッドとappendreverseextendpopremove、および [ X103X]
Set サイズ反復可能コンテナ __contains____iter____len__ __le____lt____eq____ne____gt____ge____and__、[ X77X] 、__sub____xor__、およびisdisjoint
MutableSet Set __contains____iter____len__adddiscard 継承された Set メソッドおよびclearpopremove__ior____iand__、 [X94X ]、および__isub__
Mapping サイズ反復可能コンテナ __getitem____iter____len__ __contains__keysitemsvaluesget__eq__、および__ne__
MutableMapping Mapping __getitem____setitem____delitem____iter____len__ 継承されたマッピングメソッドとpoppopitemclearupdate、およびsetdefault
MappingView Sized __len__
ItemsView MappingViewSet __contains____iter__
KeysView MappingViewSet __contains____iter__
ValuesView MappingView __contains____iter__
class collections.Container

class collections.Hashable
class collections.Sized
class collections.Callable

メソッド__contains__()__hash__()__len__()、および__call__()をそれぞれ提供するクラスのABC。
class collections.Iterable
__iter__()メソッドを提供するクラスのABC。 iterable の定義も参照してください。
class collections.Iterator
__ iter __()および next()メソッドを提供するクラスのABC。 イテレータの定義も参照してください。
class collections.Sequence

class collections.MutableSequence

読み取り専用で変更可能なシーケンスのABC。
class collections.Set

class collections.MutableSet

読み取り専用および可変セットのABC。
class collections.Mapping

class collections.MutableMapping

読み取り専用で変更可能なマッピングのABC。
class collections.MappingView

class collections.ItemsView
class collections.KeysView
class collections.ValuesView

マッピング、アイテム、キー、および値のABC ビュー

これらのABCを使用すると、クラスまたはインスタンスに特定の機能を提供しているかどうかを尋ねることができます。次に例を示します。

size = None
if isinstance(myvar, collections.Sized):
    size = len(myvar)

ABCのいくつかは、コンテナAPIをサポートするクラスの開発を容易にするミックスインとしても役立ちます。 たとえば、完全な Set APIをサポートするクラスを作成するには、基礎となる3つの抽象メソッド__contains__()__iter__()、および__len__()を指定するだけで済みます。 ]。 ABCは、__and__()isdisjoint()などの残りのメソッドを提供します。

class ListBasedSet(collections.Set):
     ''' Alternate set implementation favoring space over speed
         and not requiring the set elements to be hashable. '''
     def __init__(self, iterable):
         self.elements = lst = []
         for value in iterable:
             if value not in lst:
                 lst.append(value)

     def __iter__(self):
         return iter(self.elements)

     def __contains__(self, value):
         return value in self.elements

     def __len__(self):
         return len(self.elements)

s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
overlap = s1 & s2            # The __and__() method is supported automatically

SetMutableSet をミックスインとして使用する際の注意事項:

  1. 一部のセット操作は新しいセットを作成するため、デフォルトのミックスインメソッドには反復可能オブジェクトから新しいインスタンスを作成する方法が必要です。 クラスコンストラクタは、ClassName(iterable)の形式の署名を持っていると想定されています。 その仮定は、cls(iterable)を呼び出して新しいセットを生成する_from_iterable()と呼ばれる内部クラスメソッドに因数分解されます。 Set ミックスインが異なるコンストラクターシグネチャを持つクラスで使用されている場合は、反復可能な引数から新しいインスタンスを構築できるclassmethodで_from_iterable()をオーバーライドする必要があります。
  2. 比較をオーバーライドするには(おそらくセマンティクスが固定されているため、速度のために)、__le__()__ge__()を再定義すると、他の操作が自動的に続きます。
  3. Set ミックスインは、セットのハッシュ値を計算するための_hash()メソッドを提供します。 ただし、すべてのセットがハッシュ可能または不変であるとは限らないため、__hash__()は定義されていません。 ミックスインを使用してセットのハッシュ機能を追加するには、 Set()Hashable()の両方から継承し、__hash__ = Set._hashを定義します。

も参照してください