辞書を「完全に」上書きする方法は?


218

どうすれば、dictのサブクラスをできるだけ「完璧」にすることができますか?最終的な目標は、キーが小文字である単純な辞書を持つことです。

これを機能させるためにオーバーライドできる小さなプリミティブのセットがあるはずですが、私のすべての研究と試みによれば、そうではないようです:

  • /オーバーライドする__getitem____setitem__と、get/が機能setしなくなります。どうすればそれらを機能させることができますか?確かに個別に実装する必要はありませんか?

  • 酸洗いが機能しないようにしてい__setstate__ますか?実装する必要がありますか?

  • 私は、DO 必要reprupdate__init__

  • 可変マッピングのみを使用する必要がありますUserDict か(またはを使用してはいけないようDictMixinです)?もしそうなら、どうですか?ドキュメントは正確には啓蒙的ではありません。

これが私の最初の試みですが、get()動作しません。間違いなく他にも多くの小さな問題があります。

class arbitrary_dict(dict):
    """A dictionary that applies an arbitrary key-altering function
       before accessing the keys."""

    def __keytransform__(self, key):
        return key

    # Overridden methods. List from 
    # /programming/2390827/how-to-properly-subclass-dict

    def __init__(self, *args, **kwargs):
        self.update(*args, **kwargs)

    # Note: I'm using dict directly, since super(dict, self) doesn't work.
    # I'm not sure why, perhaps dict is not a new-style class.

    def __getitem__(self, key):
        return dict.__getitem__(self, self.__keytransform__(key))

    def __setitem__(self, key, value):
        return dict.__setitem__(self, self.__keytransform__(key), value)

    def __delitem__(self, key):
        return dict.__delitem__(self, self.__keytransform__(key))

    def __contains__(self, key):
        return dict.__contains__(self, self.__keytransform__(key))


class lcdict(arbitrary_dict):
    def __keytransform__(self, key):
        return str(key).lower()

__keytransform __()は静的でなければなりません。素晴らしいアプローチですが。(前に@staticmethod)
Aiyion.Prime 2018

回答:


229

モジュールからABC(抽象基底クラス)を使用するdictと、非常に簡単に動作するオブジェクトを作成できます。メソッドを見逃したかどうかもわかるので、以下はABCをシャットダウンする最小バージョンです。collections.abc

from collections.abc import MutableMapping


class TransformedDict(MutableMapping):
    """A dictionary that applies an arbitrary key-altering
       function before accessing the keys"""

    def __init__(self, *args, **kwargs):
        self.store = dict()
        self.update(dict(*args, **kwargs))  # use the free update to set keys

    def __getitem__(self, key):
        return self.store[self.__keytransform__(key)]

    def __setitem__(self, key, value):
        self.store[self.__keytransform__(key)] = value

    def __delitem__(self, key):
        del self.store[self.__keytransform__(key)]

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

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

    def __keytransform__(self, key):
        return key

ABCからいくつかの無料のメソッドを取得します。

class MyTransformedDict(TransformedDict):

    def __keytransform__(self, key):
        return key.lower()


s = MyTransformedDict([('Test', 'test')])

assert s.get('TEST') is s['test']   # free get
assert 'TeSt' in s                  # free __contains__
                                    # free setdefault, __eq__, and so on

import pickle
# works too since we just use a normal dict
assert pickle.loads(pickle.dumps(s)) == s

サブクラスdict(または他の組み込み関数)を直接サブクラス化しません。あなたが実際にしたいことはのインターフェースを実装するdictことなので、それはしばしば意味をなさない。そして、それこそがABCの目的です。


46
説明:名前付けスタイルのセクションの__keytransform__()最後にある「そのような名前を発明することはせず、文書化されているとおりにのみ使用する」ことを推奨するPEP 8スタイルガイドに違反しているため、名前の変更をお勧めします。
martineau

1
ただし、このインターフェイスをユーザー定義型で実装すると、通常、組み込み型を使用するよりもdictのような動作が遅くなりますか?
twneale 2013

2
isinstance(_、dict)== Trueになるようにこれを行う方法はありますか?または、可変マッピングを使用してサブクラスを作成しますか?
アンディヘイデン

5
@AndyHayden:書いてくださいif isinstance(t, collections.MutableMapping): print t, "can be used like a dict"。オブジェクトのタイプはチェックせず、インターフェースをチェックしてください。
Jochen Ritzel 14年

2
@NeilGこれは残念ながら、Pythonの標準ライブラリにJSONEncoderを含んで- github.com/python-git/python/blob/...
アンディ・スミス

97

どうすれば、dictのサブクラスをできるだけ「完璧」にすることができますか?

最終的な目標は、キーが小文字である単純な辞書を持つことです。

  • __getitem__/ をオーバーライドする__setitem__と、get / setが機能しなくなります。それらをどのように機能させるのですか?確かに個別に実装する必要はありませんか?

  • 酸洗いが機能しないようにしてい__setstate__ますか?実装する必要があり ますか?

  • repr、update、および必要__init__ですか?

  • 私はちょうど使用する必要がありますmutablemapping(それは1つが使うべきではないと思われますUserDictDictMixin)?もしそうなら、どうですか?ドキュメントは正確には啓蒙的ではありません。

受け入れられた答えは私の最初のアプローチですが、いくつかの問題があり、誰も代替案に取り組んでいないため、実際にはをサブクラス化dictしているので、ここでそれを行います。

受け入れられた答えの何が問題になっていますか?

これは私にはかなり単純な要求のようです:

どうすれば、dictのサブクラスをできるだけ「完璧」にすることができますか?最終的な目標は、キーが小文字である単純な辞書を持つことです。

受け入れられた答えは実際にはサブクラスdictではなく、これに対するテストは失敗します:

>>> isinstance(MyTransformedDict([('Test', 'test')]), dict)
False

理想的には、型チェックコードは、期待するインターフェイスまたは抽象基本クラスをテストすることになりますが、データオブジェクトがテスト対象の関数に渡されておりdict、これらの関数を「修正」できない場合、このコード失敗します。

人が作るかもしれない他の問題:

  • 受け入れられた回答にもclassmethod:がありませんfromkeys
  • 受け入れられた回答にも冗長性があります__dict__-したがって、メモリ内でより多くのスペースを使用します。

    >>> s.foo = 'bar'
    >>> s.__dict__
    {'foo': 'bar', 'store': {'test': 'test'}}

実際にサブクラス化 dict

継承を通じてdictメソッドを再利用できます。文字列の場合、キーが小文字の形式でdictに渡されるようにするインターフェイスレイヤーを作成するだけです。

__getitem__/ をオーバーライドする__setitem__と、get / setが機能しなくなります。それらをどのように機能させるのですか?確かに個別に実装する必要はありませんか?

まあ、それらをそれぞれ個別に実装することは、このアプローチの欠点であり、使用することのメリットですMutableMapping(承認された回答を参照)。

まず、Python 2と3の違いを_RaiseKeyError考えてみましょう。シングルトン()を作成して、実際にへの引数を取得するかどうかをdict.pop確認し、文字列キーが小文字であることを確認する関数を作成します。

from itertools import chain
try:              # Python 2
    str_base = basestring
    items = 'iteritems'
except NameError: # Python 3
    str_base = str, bytes, bytearray
    items = 'items'

_RaiseKeyError = object() # singleton for no-default behavior

def ensure_lower(maybe_str):
    """dict keys can be any hashable object - only call lower if str"""
    return maybe_str.lower() if isinstance(maybe_str, str_base) else maybe_str

今すぐ実装します- superこのコードがPython 2および3で機能するように、完全な引数を使用しています。

class LowerDict(dict):  # dicts take a mapping or iterable as their optional first argument
    __slots__ = () # no __dict__ - that would be redundant
    @staticmethod # because this doesn't make sense as a global function.
    def _process_args(mapping=(), **kwargs):
        if hasattr(mapping, items):
            mapping = getattr(mapping, items)()
        return ((ensure_lower(k), v) for k, v in chain(mapping, getattr(kwargs, items)()))
    def __init__(self, mapping=(), **kwargs):
        super(LowerDict, self).__init__(self._process_args(mapping, **kwargs))
    def __getitem__(self, k):
        return super(LowerDict, self).__getitem__(ensure_lower(k))
    def __setitem__(self, k, v):
        return super(LowerDict, self).__setitem__(ensure_lower(k), v)
    def __delitem__(self, k):
        return super(LowerDict, self).__delitem__(ensure_lower(k))
    def get(self, k, default=None):
        return super(LowerDict, self).get(ensure_lower(k), default)
    def setdefault(self, k, default=None):
        return super(LowerDict, self).setdefault(ensure_lower(k), default)
    def pop(self, k, v=_RaiseKeyError):
        if v is _RaiseKeyError:
            return super(LowerDict, self).pop(ensure_lower(k))
        return super(LowerDict, self).pop(ensure_lower(k), v)
    def update(self, mapping=(), **kwargs):
        super(LowerDict, self).update(self._process_args(mapping, **kwargs))
    def __contains__(self, k):
        return super(LowerDict, self).__contains__(ensure_lower(k))
    def copy(self): # don't delegate w/ super - dict.copy() -> dict :(
        return type(self)(self)
    @classmethod
    def fromkeys(cls, keys, v=None):
        return super(LowerDict, cls).fromkeys((ensure_lower(k) for k in keys), v)
    def __repr__(self):
        return '{0}({1})'.format(type(self).__name__, super(LowerDict, self).__repr__())

私たちは、任意の方法または特別法のために、ほとんどのボイラープレート・アプローチを使用するが参照するキーが、それ以外は、継承によって、我々はメソッドを取得:lenclearitemskeyspopitem、そしてvalues自由のために。これを正しく行うには慎重な検討が必要ですが、これが機能することは簡単です。

haskeyPython 2では非推奨になり、Python 3で削除されました。)

ここにいくつかの使用法があります:

>>> ld = LowerDict(dict(foo='bar'))
>>> ld['FOO']
'bar'
>>> ld['foo']
'bar'
>>> ld.pop('FoO')
'bar'
>>> ld.setdefault('Foo')
>>> ld
{'foo': None}
>>> ld.get('Bar')
>>> ld.setdefault('Bar')
>>> ld
{'bar': None, 'foo': None}
>>> ld.popitem()
('bar', None)

酸洗いが機能しないようにしてい__setstate__ますか?実装する必要があり ますか?

酸洗い

そしてdictサブクラスはピクルスでうまくいきます:

>>> import pickle
>>> pickle.dumps(ld)
b'\x80\x03c__main__\nLowerDict\nq\x00)\x81q\x01X\x03\x00\x00\x00fooq\x02Ns.'
>>> pickle.loads(pickle.dumps(ld))
{'foo': None}
>>> type(pickle.loads(pickle.dumps(ld)))
<class '__main__.LowerDict'>

__repr__

repr、update、および必要__init__ですか?

とを定義updateしましたが__init____repr__デフォルトでは美しいです。

>>> ld # without __repr__ defined for the class, we get this
{'foo': None}

ただし、__repr__コードのデバッグ性を向上させるためにを書くことは良いことです。理想的なテストはeval(repr(obj)) == objです。コードで簡単に実行できる場合は、次のことを強くお勧めします。

>>> ld = LowerDict({})
>>> eval(repr(ld)) == ld
True
>>> ld = LowerDict(dict(a=1, b=2, c=3))
>>> eval(repr(ld)) == ld
True

ご覧のとおり、同等のオブジェクトを再作成するために必要なものです。これは、ログまたはバックトレースに表示される可能性があるものです。

>>> ld
LowerDict({'a': 1, 'c': 3, 'b': 2})

結論

私はちょうど使用する必要がありますmutablemapping(それは1つが使うべきではないと思われますUserDictDictMixin)?もしそうなら、どうですか?ドキュメントは正確には啓蒙的ではありません。

ええ、これらはさらに数行のコードですが、包括的であることを目的としています。私の最初の傾向は、受け入れられた回答を使用することであり、それに問題がある場合は、私の回答を調べます。少し複雑で、インターフェースを正しくするためのABCがありません。

時期尚早な最適化は、パフォーマンスを追求する上でさらに複雑になります。 MutableMappingより単純です-したがって、すぐに優位に立ち、他のすべては等しくなります。それでも、すべての違いを明らかにするために、比較して対比しましょう。

同様のディクショナリをcollectionsモジュールに挿入するように要求されたが、拒否されことを付け加えておきます。あなたはおそらく代わりにこれを行うべきです:

my_dict[transform(key)]

はるかに簡単にデバッグできるはずです。

比較対照

MutableMapping(欠落fromkeys)で実装された6つのインターフェース関数と、dictサブクラスで実装された11のインターフェース関数があります。私が実装する必要はありません__iter____len__、代わりに私が実装する必要がありgetsetdefaultpopupdatecopy__contains__、とfromkeys私はそれらの実装のほとんどのための継承を使用することができるので、これらはかなり些細です- 。

MutableMapping道具PythonでいくつかのものというdictCで実装-私が期待するように、dictサブクラスがいくつかのケースでよりパフォーマンスします。

__eq__両方のアプローチで自由が得られます-どちらも、別の辞書がすべて小文字である場合にのみ同等であると仮定します-しかし、繰り返しになりますが、dictサブクラスはより速く比較されると思います。

概要:

  • サブクラス化MutableMappingは単純で、バグが発生する可能性は少なくなりますが、遅くなり、より多くのメモリを消費し(冗長な辞書を参照)、失敗しますisinstance(x, dict)
  • サブクラス化dictは高速で、使用するメモリが少なく、合格しますがisinstance(x, dict)、実装が複雑になります。

どちらがより完璧ですか?それはあなたの完璧の定義に依存します。


受け入れられた答えはどのようにして冗長な口述を取り除くでしょうか?
Seanny123 2017年

1
すぐに頭に浮かぶ2つの方法は、ストア属性をストアで宣言するか、__slots__おそらく__dict__ストアとして再利用することですが、これはセマンティクスを混合することであり、批判のもう1つの潜在的なポイントです。
アーロンホール

1
メソッドを受け取りensure_lower、最初の引数(常にキー)を使用するデコレータを作成する方が簡単だったでしょうか。次に、オーバーライドの数は同じになりますが、すべてがの形式になり__getitem__ = ensure_lower_decorator(super(LowerDict, self).__getitem__)ます。
Graipher

1
これをありがとう-popおよびfromkeysに対して、基本クラスメソッドのシグネチャと一致しないという警告が表示されます。
Mr_and_Mrs_D 2017年

1
@Mr_and_Mrs_Dの実装を追加しましたcopy-そうすべきだと思いますか?インターフェイスをテストする必要があると思います。たとえば、pandas DataFrameオブジェクトは(最後のチェックで)Mappingインスタンスではありませんが、アイテム/ iteritemsはあります。
アーロンホール

4

私の要件は少し厳しかった:

  • 大文字と小文字の情報を保持する必要がありました(文字列はユーザ​​ーに表示されるファイルへのパスですが、これはWindowsアプリなので、内部的にはすべての操作で大文字と小文字を区別する必要があります)
  • 私は(それが可能な限り小さくするキーを必要としなかったメモリのパフォーマンスの違いを作る、370のうち110メガバイトを切り落とし)。つまり、小文字のバージョンのキーをキャッシュすることはオプションではありません。
  • データ構造の作成をできるだけ速くする必要がありました(今回もパフォーマンスに違いがあり、速度が向上しました)。ビルトインに行かなければならなかった

私の最初の考えは、大文字と小文字を区別しないユニコードサブクラスを、不格好なPathクラスに置き換えることでしたが、次のとおりです。

  • それを正しく行うのが難しいことが判明-参照:Pythonの大文字と小文字を区別しない文字列クラス
  • 明示的なdictキーの処理により、コードが冗長で乱雑になり、エラーが発生しやすくなります(構造体が何度も渡されるため、CIStrインスタンスがキー/要素として存在するかどうかはわかりませんが、簡単に忘れてしまいますsome_dict[CIstr(path)]

それで、私はようやくその大文字小文字を区別しない辞書を書き留める必要がありました。@AaronHallによるコードのおかげで10倍簡単になりました。

class CIstr(unicode):
    """See https://stackoverflow.com/a/43122305/281545, especially for inlines"""
    __slots__ = () # does make a difference in memory performance

    #--Hash/Compare
    def __hash__(self):
        return hash(self.lower())
    def __eq__(self, other):
        if isinstance(other, CIstr):
            return self.lower() == other.lower()
        return NotImplemented
    def __ne__(self, other):
        if isinstance(other, CIstr):
            return self.lower() != other.lower()
        return NotImplemented
    def __lt__(self, other):
        if isinstance(other, CIstr):
            return self.lower() < other.lower()
        return NotImplemented
    def __ge__(self, other):
        if isinstance(other, CIstr):
            return self.lower() >= other.lower()
        return NotImplemented
    def __gt__(self, other):
        if isinstance(other, CIstr):
            return self.lower() > other.lower()
        return NotImplemented
    def __le__(self, other):
        if isinstance(other, CIstr):
            return self.lower() <= other.lower()
        return NotImplemented
    #--repr
    def __repr__(self):
        return '{0}({1})'.format(type(self).__name__,
                                 super(CIstr, self).__repr__())

def _ci_str(maybe_str):
    """dict keys can be any hashable object - only call CIstr if str"""
    return CIstr(maybe_str) if isinstance(maybe_str, basestring) else maybe_str

class LowerDict(dict):
    """Dictionary that transforms its keys to CIstr instances.
    Adapted from: https://stackoverflow.com/a/39375731/281545
    """
    __slots__ = () # no __dict__ - that would be redundant

    @staticmethod # because this doesn't make sense as a global function.
    def _process_args(mapping=(), **kwargs):
        if hasattr(mapping, 'iteritems'):
            mapping = getattr(mapping, 'iteritems')()
        return ((_ci_str(k), v) for k, v in
                chain(mapping, getattr(kwargs, 'iteritems')()))
    def __init__(self, mapping=(), **kwargs):
        # dicts take a mapping or iterable as their optional first argument
        super(LowerDict, self).__init__(self._process_args(mapping, **kwargs))
    def __getitem__(self, k):
        return super(LowerDict, self).__getitem__(_ci_str(k))
    def __setitem__(self, k, v):
        return super(LowerDict, self).__setitem__(_ci_str(k), v)
    def __delitem__(self, k):
        return super(LowerDict, self).__delitem__(_ci_str(k))
    def copy(self): # don't delegate w/ super - dict.copy() -> dict :(
        return type(self)(self)
    def get(self, k, default=None):
        return super(LowerDict, self).get(_ci_str(k), default)
    def setdefault(self, k, default=None):
        return super(LowerDict, self).setdefault(_ci_str(k), default)
    __no_default = object()
    def pop(self, k, v=__no_default):
        if v is LowerDict.__no_default:
            # super will raise KeyError if no default and key does not exist
            return super(LowerDict, self).pop(_ci_str(k))
        return super(LowerDict, self).pop(_ci_str(k), v)
    def update(self, mapping=(), **kwargs):
        super(LowerDict, self).update(self._process_args(mapping, **kwargs))
    def __contains__(self, k):
        return super(LowerDict, self).__contains__(_ci_str(k))
    @classmethod
    def fromkeys(cls, keys, v=None):
        return super(LowerDict, cls).fromkeys((_ci_str(k) for k in keys), v)
    def __repr__(self):
        return '{0}({1})'.format(type(self).__name__,
                                 super(LowerDict, self).__repr__())

暗黙的か明示的かはまだ問題ですが、ひとたび落ち着くと、ciで始まる属性/変数の名前を変更します(そして、ciは大文字と小文字を区別しないことを説明する大きな太いドキュメントのコメント)私は完璧な解決策だと思います-コードの読者は大文字と小文字を区別しない基本的なデータ構造を扱っていることを十分に認識してください。これにより、再現が難しいいくつかのバグが修正され、大文字と小文字が区別されると思います。

コメント/修正は歓迎します:)


CIstr __repr__は親クラスを使用し__repr__てeval(repr(obj))== objテストに合格する必要があります(現時点ではそうではないと思います)__str__
アーロンホール

また、total_orderingクラスデコレータも確認してください。これにより、Unicodeサブクラスから4つのメソッドが削除されます。しかし、dictサブクラスは非常に巧妙に実装されているように見えます。:P
アーロンホール

ありがとう@AaronHall-それを実装したのはあなたです:P Re:完全な順序付け-私はレイモンドヘッティンガーのアドバイスに従ってメソッドをインラインで意図的に記述しました:stackoverflow.com/a/43122305/281545。Re:repr:私は(一部のコア開発者IIRCによる)コメントを読んだことを覚えていますが、テストに合格するためにreprを作成するのはそれほど面倒なことではありません(面倒です)。それ以上はありません)
Mr_and_Mrs_D 2017

私はあなた、あなたの冗長比較方法(あなたがあなたの答えでそれについてメモしておく必要がある)ことができます、しかしCIstr.__repr__、中にあなたの場合、非常に少ない手間でのrepr試験に合格することができ、そしてそれは多くのよりよいのデバッグを行う必要があります。私も__repr__あなたの辞書に追加します。私はデモンストレーションするために私の答えでそれをします。
アーロンホール

@AaronHall:CIstrに追加__slots__しました-パフォーマンスに違いがあります(CIstrはサブクラス化することを意図しておらず、実際にLowerDictの外部で使用することを意図しておらず、静的にネストされた最終クラスである必要があります)。reprの問題をエレガントに解決する方法はまだわかりません(スティングには'"引用符の組み合わせが含まれる場合があります)
Mr_and_Mrs_D

4

あなたがしなければならないのは、

class BatchCollection(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(*args, **kwargs)

または

class BatchCollection(dict):
    def __init__(self, inpt={}):
        super(BatchCollection, self).__init__(inpt)

私の個人使用の使用例

### EXAMPLE
class BatchCollection(dict):
    def __init__(self, inpt={}):
        dict.__init__(*args, **kwargs)

    def __setitem__(self, key, item):
        if (isinstance(key, tuple) and len(key) == 2
                and isinstance(item, collections.Iterable)):
            # self.__dict__[key] = item
            super(BatchCollection, self).__setitem__(key, item)
        else:
            raise Exception(
                "Valid key should be a tuple (database_name, table_name) "
                "and value should be iterable")

:python3でのみテスト済み


3

上位 2つの提案の両方を試した後、私はPython 2.7の怪しげな中間ルートに落ち着きました。多分3は正気ですが、私にとっては:

class MyDict(MutableMapping):
   # ... the few __methods__ that mutablemapping requires
   # and then this monstrosity
   @property
   def __class__(self):
       return dict

私は本当に嫌いですが、私のニーズに合うようです:

  • 上書きできる **my_dict
    • から継承する場合dictこれはコードをバイパスします。やってみよう。
    • これは#2 を常に受け入れられないようにします。これはPythonコードでは非常に一般的であるためです。
  • 仮面舞踏会 isinstance(my_dict, dict)
    • MutableMappingのみを除外するため、#1では不十分
    • これが必要ない場合は、1をお勧めします。シンプルで予測可能です。
  • 完全に制御可能な動作
    • から継承できません dict

他の人と区別する必要がある場合は、個人的に次のようなものを使用します(ただし、より適切な名前をお勧めします)。

def __am_i_me(self):
  return True

@classmethod
def __is_it_me(cls, other):
  try:
    return other.__am_i_me()
  except Exception:
    return False

内部的に自分を認識するだけでよい限り、このようにすると__am_i_me、Pythonの名前変更(これは、_MyDict__am_i_meこのクラスの外部からの呼び出しから名前が変更されます)が原因で誤って呼び出すことが難しくなります。_method実際よりも文化的にも、s よりも少しプライベートです。

これまでのところ、深刻な陰のように見える__class__オーバーライドを除いて、私は不満はありません。他の人がこれで遭遇する問題を聞いて私は興奮しますが、私はその結果を完全に理解していません。しかし、これまでのところ問題はありませんでした。これにより、変更を必要とせずに、多くの場所で中程度の品質のコードを移行することができました。


証拠として:https : //repl.it/repls/TraumaticToughCockatoo

基本的に:現在の#2オプションをコピーしprint 'method_name'すべてのメソッドに行を追加してから、これを試して出力を確認します。

d = LowerDict()  # prints "init", or whatever your print statement said
print '------'
splatted = dict(**d)  # note that there are no prints here

他のシナリオでも同様の動作が見られます。あなたの偽物dictが他のいくつかのデータ型のラッパーであるとしましょう。そのため、データをbacking-dictに格納する合理的な方法はありません。**your_dict他のすべてのメソッドの動作に関係なく、空になります。

これはで正しく機能MutableMappingしますが、継承するとすぐにdict制御できなくなります。


編集:更新として、これは現在約2年間、単一の問題なしで実行されており、数十万行(ええと、数百万行かもしれません)の複雑でレガシーに覆われたPythonで実行されています。だから私はそれにとても満足しています:)

編集2:どうやら、私はこれまたはかなり前に何かを誤ってコピーしました。 チェックで@classmethod __class__は機能しませんisinstance- @property __class__機能します:https : //repl.it/repls/UnitedScientificSequence


**your_dict空になる」とはどういう意味ですか(からサブクラス化する場合dict)?dictの解凍に問題はありませんでした...
Matt P

実際にデータを親dictに入れれば(LowerDictのように)、それは機能します-dictに保存されたデータを取得します。そうでない場合(たとえば、{access_count: "stack trace of access"}が読み込まれるたびに入力するデータをその場で生成したいと思った場合)、**your_dictコードが実行されないことに気づくでしょう。「特別」なものは何も出力できません。たとえば、読み取りカウントコードを実行しないため、「読み取り」をカウントできません。MutableMapping はこれで機能します(可能な場合は使用してください)。ただし、失敗するisinstance(..., dict)ため使用できませんでした。いやレガシーソフトウェア。
Groxx

わかりました、あなたの今の意味がわかります。でのコード実行を期待していなかっ**your_dictたと思いますが、それを実行することは非常に興味深いMutableMappingと思います。
マットP

うん。それは多くの事柄に必要であり(たとえば、RPC呼び出しをlocal-dictの読み取りに使用し、Reasons™のオンデマンドで実行する必要がありました)、それを知っている人はほとんどいません。**some_dictかなり一般的です。少なくとも、それはデコレータで非常に頻繁に発生するため、何かがある場合、それを考慮しないと、一見不可能に思われる不正な動作の危険にさらされます。
Groxx

多分私は何かが足りないかもしれdef __class__()ませんが、トリックは少なくとも質問2の例のコードではPython 2または3のどちらでも機能しないようです。(2つのバージョンで動作するように変更されています)。私が欲しいisinstance(SpreadSheet(), dict)返すようにTrue
martineau
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.