ホームページ >バックエンド開発 >Python チュートリアル >Pythonのdefaultdictの詳しい解説(コード例)

Pythonのdefaultdictの詳しい解説(コード例)

不言
不言転載
2018-10-25 17:34:433199ブラウズ

この記事では、Python のdefaultdict の詳細な説明 (コード例) を紹介します。一定の参考値があります。必要な友人は参照してください。お役に立てば幸いです。

デフォルト値は非常に便利です

ご存知のとおり、Python では、辞書に存在しないキーにアクセスすると、KeyError 例外が発生します。が発生します (JavaScript では、オブジェクト属性に特定のキーが存在しない場合、unknown が返されます)。ただし、辞書内のすべてのキーにデフォルト値があると非常に便利な場合があります。たとえば、次の例は次のとおりです。

strings = ('puppy', 'kitten', 'puppy', 'puppy',
           'weasel', 'puppy', 'kitten', 'puppy')
counts = {}
for kw in strings:
    counts[kw] += 1

この例では、文字列内に単語が出現する回数をカウントし、カウント ディクショナリに記録します。単語が出現するたびに、カウントに対応するキーに格納されている値が 1 ずつ増加します。しかし、実際には、このコードを実行すると KeyError 例外がスローされます。発生のタイミングは、各単語が初めてカウントされたときです。Python の辞書にはデフォルト値がないため、Python コマンド ラインで確認できます:

>>> counts = dict()
>>> counts
{}
>>> counts['puppy'] += 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: &#39;puppy&#39;

判定ステートメントを使用して確認する

この場合、最初に思いつく方法は、単語を初めてカウントするときに、対応するカウント数のキーにデフォルト値 1 を格納することです。これには、処理中に判断ステートメントを追加する必要があります:
strings = (&#39;puppy&#39;, &#39;kitten&#39;, &#39;puppy&#39;, &#39;puppy&#39;,
           &#39;weasel&#39;, &#39;puppy&#39;, &#39;kitten&#39;, &#39;puppy&#39;)
counts = {}
for kw in strings:
    if kw not in counts:
        counts[kw] = 1
    else:
        counts[kw] += 1
# counts:
# {&#39;puppy&#39;: 5, &#39;weasel&#39;: 1, &#39;kitten&#39;: 2}

dict.setdefault() メソッドを使用します

また、dict.setdefault() メソッドを通じてデフォルト値を設定することもできます:

strings = (&#39;puppy&#39;, &#39;kitten&#39;, &#39;puppy&#39;, &#39;puppy&#39;,
           &#39;weasel&#39;, &#39;puppy&#39;, &#39;kitten&#39;, &#39;puppy&#39;)
counts = {}
for kw in strings:
    counts.setdefault(kw, 0)
    counts[kw] += 1

dict.setdefault() メソッドは 2 つのパラメータを受け取ります。最初のパラメータはキーの名前で、2 番目のパラメータはデフォルト値です。指定されたキーがディクショナリに存在しない場合は、パラメータに指定されたデフォルト値が返され、それ以外の場合は、ディクショナリに保存されている値が返されます。 for ループ内のコードは、dict.setdefault() メソッドの戻り値を使用してより簡潔にするために書き直すことができます。

strings = (&#39;puppy&#39;, &#39;kitten&#39;, &#39;puppy&#39;, &#39;puppy&#39;,
           &#39;weasel&#39;, &#39;puppy&#39;, &#39;kitten&#39;, &#39;puppy&#39;)
counts = {}
for kw in strings:
    counts[kw] = counts.setdefault(kw, 0) + 1

Collections.defaultdict クラスを使用します。これで辞書にデフォルト値がないという問題はある程度解決しますが、このとき疑問に思うのは、辞書自体にデフォルト値の機能を提供するものがあるのか​​ということです。答えは「はい」です、それは collections.defaultdict です。

defaultdict クラスは dict に似ていますが、タイプを使用して初期化されます:

>>> from collections import defaultdict
>>> dd = defaultdict(list)
>>> dd
defaultdict(<type &#39;list&#39;>, {})

defaultdict クラスの初期化関数は、パラメータとしてタイプを受け入れます。アクセスされるキーが存在しない場合、それは値をデフォルト値として変更します:

>>> dd[&#39;foo&#39;]
[]
>>> dd
defaultdict(<type &#39;list&#39;>, {&#39;foo&#39;: []})
>>> dd[&#39;bar&#39;].append(&#39;quux&#39;)
>>> dd
defaultdict(<type &#39;list&#39;>, {&#39;foo&#39;: [], &#39;bar&#39;: [&#39;quux&#39;]})

この形式のデフォルト値は、

dict[key] または dict を介してのみ渡されることに注意してください。 __getitem__(key)アクセス時のみ有効 以下にその理由を紹介します。

>>> from collections import defaultdict
>>> dd = defaultdict(list)
>>> &#39;something&#39; in dd
False
>>> dd.pop(&#39;something&#39;)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: &#39;pop(): dictionary is empty&#39;
>>> dd.get(&#39;something&#39;)
>>> dd[&#39;something&#39;]
[]

このクラスは、初期化関数のパラメータとして型名を受け入れることに加えて、パラメータなしで呼び出し可能な関数を使用することもできます。その際、関数の戻り結果がデフォルト値として使用されます。これにより、デフォルト値の値がより柔軟になります。次の例では、初期化関数のパラメーターとしてパラメーターなしでカスタム関数 zero() を使用する方法を示しています。

>>> from collections import defaultdict
>>> def zero():
...     return 0
...
>>> dd = defaultdict(zero)
>>> dd
defaultdict(<function zero at 0xb7ed2684>, {})
>>> dd[&#39;foo&#39;]
0
>>> dd
defaultdict(<function zero at 0xb7ed2684>, {&#39;foo&#39;: 0})

collections.defaultdict を使用して、初期単語統計の問題を解決します。

from collections import defaultdict
strings = (&#39;puppy&#39;, &#39;kitten&#39;, &#39;puppy&#39;, &#39;puppy&#39;,
           &#39;weasel&#39;, &#39;puppy&#39;, &#39;kitten&#39;, &#39;puppy&#39;)
counts = defaultdict(lambda: 0)  # 使用lambda来定义简单的函数
for s in strings:
    counts[s] += 1

defaultdict クラスの実装方法

上記の内容を通じて、defaultdict クラスの使用法を理解したはずです。つまり、デフォルト値を実装する方法は次のとおりです。 defaultdict クラス関数についてはどうですか?これの鍵となるのは、__missing__() メソッドの使用です。

>>> from collections import defaultdict
>>> print defaultdict.__missing__.__doc__
__missing__(key) # Called by __getitem__ for missing key; pseudo-code:
  if self.default_factory is None: raise KeyError(key)
  self[key] = value = self.default_factory()
  return value

__missing__() メソッドの docstring を見ると、存在しないオブジェクトにアクセスするために __getitem__() メソッドを使用していることがわかります。 key (形式 dict[key] は実際には __getitem__() メソッドの簡略化された形式です)。このメソッドは __missing__() メソッドを呼び出してデフォルト値を取得し、キーを辞書に追加します。

__missing__() メソッドの詳細については、Python の公式ドキュメントの「マッピング タイプ — dict」セクションを参照してください。

バージョン 2.5 以降、ドキュメントで導入されました。dict から派生したサブクラスが __missing__() メソッドを定義している場合、存在しないキーにアクセスするときに、dict[key] は __missing__() メソッドを呼び出して取得します。デフォルト値。

このことから、dict は __missing__() メソッドをサポートしていますが、このメソッドは dict 自体には存在せず、派生サブクラスに実装する必要があることがわかります。これは簡単に検証できます:

>>> print dict.__missing__.__doc__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object &#39;dict&#39; has no attribute &#39;__missing__&#39;

同時に、さらなる実験を行ってサブクラス Missing を定義し、__missing__() メソッドを実装できます:

>>> class Missing(dict):
...     def __missing__(self, key):
...         return 'missing'
...
>>> d = Missing()
>>> d
{}
>>> d['foo']
'missing'
>>> d
{}
戻り結果は __missing__( ) メソッドは機能します。これに基づいて、__missing__() メソッドをわずかに変更して、このサブクラスが defautldict クラスのような存在しないキーのデフォルト値を設定するようにします。

>>> class Defaulting(dict):
...     def __missing__(self, key):
...         self[key] = &#39;default&#39;
...         return &#39;default&#39;
...
>>> d = Defaulting()
>>> d
{}
>>> d[&#39;foo&#39;]
&#39;default&#39;
>>> d
{&#39;foo&#39;: &#39;default&#39;}

古いバージョンの Python でのdefaultdict の関数の実装

defaultdict クラスはバージョン 2.5 以降に追加されましたが、一部の古いバージョンではサポートされていないため、古いバージョンに対して互換性のあるdefaultdict クラスを実装する必要があります。これは実際には非常に単純で、パフォーマンスはバージョン 2.5 に付属の defautldict クラスほど良くないかもしれませんが、機能的には同じです。

まず第一に、アクセス キーが失敗した場合、 __getitem__() メソッドは __missing__() メソッドを呼び出す必要があります。

class defaultdict(dict):
    def __getitem__(self, key):
        try:
            return dict.__getitem__(self, key)
        except KeyError:
            return self.__missing__(key)

次に、

__missing__() メソッドを実装する必要があります。デフォルト値を設定するには:

class defaultdict(dict):
    def __getitem__(self, key):
        try:
            return dict.__getitem__(self, key)
        except KeyError:
            return self.__missing__(key)
    def __missing__(self, key):
        self[key] = value = self.default_factory()
        return value

次に、defaultdict クラスの初期化関数

__init__() は型または呼び出し可能な関数パラメーターを受け入れる必要があります:

class defaultdict(dict):
    def __init__(self, default_factory=None, *a, **kw):
        dict.__init__(self, *a, **kw)
        self.default_factory = default_factory    def __getitem__(self, key):
        try:
            return dict.__getitem__(self, key)
        except KeyError:
            return self.__missing__(key)
    def __missing__(self, key):
        self[key] = value = self.default_factory()
        return value

最后,综合以上内容,通过以下方式完成兼容新旧Python版本的代码:

try:
    from collections import defaultdictexcept ImportError:
    class defaultdict(dict):
      def __init__(self, default_factory=None, *a, **kw):
          dict.__init__(self, *a, **kw)
          self.default_factory = default_factory      def __getitem__(self, key):
          try:
              return dict.__getitem__(self, key)
          except KeyError:
              return self.__missing__(key)

      def __missing__(self, key):
          self[key] = value = self.default_factory()
          return value

以上がPythonのdefaultdictの詳しい解説(コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。