64

キーのキー値を返すpython辞書を作成したいのですが、辞書にありません。

使用例:

dic = smart_dict()
dic['a'] = 'one a'
print(dic['a'])
# >>> one a
print(dic['b'])
# >>> b
4

6 に答える 6

89

dictこれには次の__missing__フックがあります。

class smart_dict(dict):
    def __missing__(self, key):
        return key

次のように単純化できます(self使用されないため):

class smart_dict(dict):
    @staticmethod
    def __missing__(key):
        return key
于 2011-06-03T15:36:40.537 に答える
34

なぜあなただ​​けを使用しないのですか

dic.get('b', 'b')

確かに、他の人が指摘するようにサブクラス化することはできますが、時々デフォルト値を持つことができることdictを思い出しておくと便利です!get

を試してみたい場合は、次の方法defaultdictを試してください。

dic = defaultdict()
dic.__missing__ = lambda key: key
dic['b'] # should set dic['b'] to 'b' and return 'b'

を除いて... まあ: AttributeError: ^collections.defaultdict^object attribute '__missing__' is read-only、したがって、サブクラス化する必要があります:

from collections import defaultdict
class KeyDict(defaultdict):
    def __missing__(self, key):
        return key

d = KeyDict()
print d['b'] #prints 'b'
print d.keys() #prints []
于 2011-06-03T15:26:34.780 に答える
15

おめでとう。あなたも標準collections.defaultdict型の無用さを発見しました。コードの悪臭のひどい山の山 が私のものと同じくらいあなたの繊細な感性を怒らせるなら、これはあなたの幸運な StackOverflow 日です。

ビルトインの3 パラメーター バリアントの禁断の驚異のおかげで、type() 役に立たないデフォルトのディクショナリ タイプを作成することは、楽しくて有益です。

dict.__missing__() の何が問題になっていますか?

過剰な定型文と衝撃的な愚かさが好きだcollections.defaultdictとすれば、期待どおりに動作するはずですが、実際にはそうではありません。公平を期すために、オプションの メソッドサブクラス化して実装するJochen Ritzel受け入れられたソリューションは、単一のデフォルト辞書のみを必要とする小規模なユースケースの優れた回避策です。dict__missing__()

しかし、この種のボイラープレートはスケーリングが不十分です。複数のデフォルト ディクショナリをインスタンス化し、それぞれが不足しているキーと値のペアを生成するための独自のわずかに異なるロジックを使用していることに気付いた場合は、産業用に強力な代替の自動化ボイラープレートが保証されます。

または少なくとも素晴らしい。壊れたものを修正しないのはなぜですか?

DefaultDict の紹介

純粋な Python の 10 行未満 (docstring、コメント、および空白を除く) で、DefaultDict不足しているキーのデフォルト値を生成するユーザー定義の callable で初期化された型を定義します。標準collections.defaultdict型に渡された callable は無駄 にパラメーターを受け入れませんDefaultDictが、型に渡された callable は次の 2 つのパラメーターを有効に受け入れます。

  1. このディクショナリの現在のインスタンス。
  2. デフォルト値を生成する現在欠落しているキー。

このタイプを考えると、sorinの質問を解くことは、Python の 1 行に短縮されます。

>>> dic = DefaultDict(lambda self, missing_key: missing_key)
>>> dic['a'] = 'one a'
>>> print(dic['a'])
one a
>>> print(dic['b'])
b

正気。やっと。

コードまたはそれが起こらなかった

def DefaultDict(keygen):
    '''
    Sane **default dictionary** (i.e., dictionary implicitly mapping a missing
    key to the value returned by a caller-defined callable passed both this
    dictionary and that key).

    The standard :class:`collections.defaultdict` class is sadly insane,
    requiring the caller-defined callable accept *no* arguments. This
    non-standard alternative requires this callable accept two arguments:

    #. The current instance of this dictionary.
    #. The current missing key to generate a default value for.

    Parameters
    ----------
    keygen : CallableTypes
        Callable (e.g., function, lambda, method) called to generate the default
        value for a "missing" (i.e., undefined) key on the first attempt to
        access that key, passed first this dictionary and then this key and
        returning this value. This callable should have a signature resembling:
        ``def keygen(self: DefaultDict, missing_key: object) -> object``.
        Equivalently, this callable should have the exact same signature as that
        of the optional :meth:`dict.__missing__` method.

    Returns
    ----------
    MappingType
        Empty default dictionary creating missing keys via this callable.
    '''

    # Global variable modified below.
    global _DEFAULT_DICT_ID

    # Unique classname suffixed by this identifier.
    default_dict_class_name = 'DefaultDict' + str(_DEFAULT_DICT_ID)

    # Increment this identifier to preserve uniqueness.
    _DEFAULT_DICT_ID += 1

    # Dynamically generated default dictionary class specific to this callable.
    default_dict_class = type(
        default_dict_class_name, (dict,), {'__missing__': keygen,})

    # Instantiate and return the first and only instance of this class.
    return default_dict_class()


_DEFAULT_DICT_ID = 0
'''
Unique arbitrary identifier with which to uniquify the classname of the next
:func:`DefaultDict`-derived type.
'''

は…わかった、この難解な魔法への呼び出しは、ビルトインの3 パラメーター バリアントへ の呼び出しtype()です。

type(default_dict_class_name, (dict,), {'__missing__': keygen,})

この 1 行は、オプションのメソッドを呼び出し元定義の callable にdictエイリアスする新しいサブクラスを動的に生成します。__missing__ボイラープレートが明確に欠けていることに注意してくださいDefaultDict。使用量は Python の 1 行に減っています。

ひどい勝利のための自動化。

于 2017-05-23T06:07:07.387 に答える
13

最初の回答者は について言及しましたが、 の任意のサブクラスをdefaultdict定義できます:__missing__dict

>>> class Dict(dict):
        def __missing__(self, key):
            return key


>>> d = Dict(a=1, b=2)
>>> d['a']
1
>>> d['z']
'z'

また、2 番目の回答者のアプローチも気に入っています。

>>> d = dict(a=1, b=2)
>>> d.get('z', 'z')
'z'
于 2011-10-18T18:27:57.990 に答える
0

サブクラスdict__getitem__メソッド。たとえば、dict を適切にサブクラス化し、 __getitem__ と __setitem__ をオーバーライドする方法

于 2011-06-03T15:25:55.010 に答える