ドット「。」の使い方 辞書のメンバーにアクセスするには?


282

ドット「。」を介してPython辞書のメンバーにアクセスできるようにするにはどうすればよいですか?

たとえば、書く代わりに mydict['val']たいと思いますmydict.val

また、この方法でネストされた辞書にアクセスしたいと思います。例えば

mydict.mydict2.val 

参照するだろう

mydict = { 'mydict2': { 'val': ... } }

20
ネストされたdictを使用する状況の多くは、タプルをキーとして持つdictと同じかそれ以上に機能し、d[a][b][c]はに置き換えられd[a, b, c]ます。
マイクグラハム

7
それは魔法ではありません:foo = {}; foo [1,2,3] = "1、2、3!"; foo.keys()=> [(1,2,3)]
ブライアンオークリー

10
ワオ。わあ。タプルが口述の鍵になることを知りませんでした。わあ、3回目。
bodacydo

3
「ハッシュ可能」なオブジェクトはすべて、dictのキーとして使用できます。ほとんどの不変オブジェクトもハッシュ可能ですが、そのすべてのコンテンツがハッシュ可能である場合に限られます。コードd [1、2、3]は、「、」が「タプル演算子の作成」であるため機能します。d [(1、2、3)]と同じです。多くの場合、タプルの宣言の前後に括弧はオプションです。
Larry Hastings

6
キー自体にドットがある場合を考えました{"my.key":"value"}か?または、キーが「from」などのキーワードの場合はどうなりますか?私はそれを2、3回検討しましたが、それは認識された利点よりも多くの問題とトラブルシューティングです。
Todor Minakov、2015年

回答:


147

私が作ったばかりのこのクラスを使用してそれを行うことができます。このクラスを使用すると、Mapオブジェクトを別の辞書(jsonシリアル化を含む)のように、またはドット表記で使用できます。私はあなたを助けたいと思います:

class Map(dict):
    """
    Example:
    m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
    """
    def __init__(self, *args, **kwargs):
        super(Map, self).__init__(*args, **kwargs)
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    self[k] = v

        if kwargs:
            for k, v in kwargs.iteritems():
                self[k] = v

    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(Map, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(Map, self).__delitem__(key)
        del self.__dict__[key]

使用例:

m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
# Add new key
m.new_key = 'Hello world!'
# Or
m['new_key'] = 'Hello world!'
print m.new_key
print m['new_key']
# Update values
m.new_key = 'Yay!'
# Or
m['new_key'] = 'Yay!'
# Delete key
del m.new_key
# Or
del m['new_key']

21
Python 3で作業するために更新.iteritems()しました.items()
berto

13
これはAttributeError、属性が存在しない場合は発生しないという点で、一般的な期待とは異なる動作をすることに注意してください。代わりに戻りNoneます。
mic_e

ディープコピーや他のシステムがサポートできるように、getstatesetstateを追加することをお勧めします。
user1363990 2017

4
コンストラクタをに簡略化できますself.update(*args,**kwargs)。また、を追加することもでき__missing__(self,key): value=self[key]= type(self)(); return valueます。次に、ドット表記を使用して、不足しているエントリを追加できます。あなたはそれがpickableになりたい場合は、追加することができます__getstate____setstate__
イェンスムンク

1
これはhasattr(Map, 'anystring') is true. which means the hasattr would always return True due to overriding __getattr__` を作成します
Xiao

264

私はいつもこれをutilファイルに保存してきました。自分のクラスのミックスインとしても使用できます。

class dotdict(dict):
    """dot.notation access to dictionary attributes"""
    __getattr__ = dict.get
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

mydict = {'val':'it works'}
nested_dict = {'val':'nested works too'}
mydict = dotdict(mydict)
mydict.val
# 'it works'

mydict.nested = dotdict(nested_dict)
mydict.nested.val
# 'nested works too'

5
非常にシンプルな答えです。IPythonでタブ補完を機能させるために私が何をする必要があるか知っていますか?クラスは__dir __(self)を実装する必要がありますが、どういうわけかそれを機能させることができません。
andreas-h 2016

8
単純化のために+1。ネストされた辞書では動作しないようです。d = {'foo': {'bar': 'baz'}}; d = dotdict(d); d.foo.bar属性エラーをスローしますが、d.foo正常に動作します。
tmthyjames 2016年

2
はい、これは複雑な入れ子構造では機能しません。
デビッド

16
:あなたは、単にのようなドット表記を再帰的にアクセス属性にgetterメソッドでdotdict型オブジェクトを返すことができます@tmthyjames python class DotDict(dict): """dot.notation access to dictionary attributes""" def __getattr__(*args): val = dict.get(*args) return DotDict(val) if type(val) is dict else val __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__
TMKasun

4
試してみたところ、アイテムが見つからない場合にエラーが発生するのではなくget返されるため、確かに悪い考えNoneです...
NichtJens

117

インストール dotmap経由でpip

pip install dotmap

やりたいことすべてを実行し、サブクラス化します dict化するので、通常の辞書のように動作します:

from dotmap import DotMap

m = DotMap()
m.hello = 'world'
m.hello
m.hello += '!'
# m.hello and m['hello'] now both return 'world!'
m.val = 5
m.val2 = 'Sam'

その上で、あなたはそれを変換することができます dictオブジェクトます。

d = m.toDict()
m = DotMap(d) # automatic conversion in constructor

これは、アクセスしたいものがすでに入っている場合 dictフォームにある場合、それをDotMapに簡単にアクセスできるようにすることができることを意味します。

import json
jsonDict = json.loads(text)
data = DotMap(jsonDict)
print data.location.city

最後に、自動的に新しい子を作成します DotMapインスタンスがため、次のようなことができます。

m = DotMap()
m.people.steve.age = 31

バンチとの比較

完全な開示:私はDotMapの作成者です。私が作ったのはBunchこれらの機能が欠け

  • 注文アイテムが追加され、その順序で繰り返されることを覚えている
  • 子の自動DotMap作成。時間を節約し、多くの階層がある場合にコードをより簡潔にします。
  • から構築し、dictすべての子dictインスタンスを再帰的に変換しますDotMap

2
:-)名前にすでにドットが含まれているキーで機能させることができますか?{"test.foo": "bar"}介してアクセスすることができますmymap.test.fooそれは素晴らしいだろう。フラットマップをディープマップに変換し、それにDotMapを適用するには、ある程度の回帰が必要ですが、それだけの価値があります。
dlite922

きちんと。タブのリスト/補完をJupyter Notebookのキーで機能させる方法はありますか?ドットスタイルのアクセスは、インタラクティブな使用にとって最も価値があります。
ドミトリ

@Dmitri Cool製品。これまで聞いたことがないので、オートコンプリートを機能させる方法がわかりません。DotMapオートコンプリートでの使用が最適です。以前入力したキーワードをオートコンプリートするSublime Textを使用しています。
Chris Redford、

1
**kwargsまたはなどの辞書抽出が不足していることがわかりましたc = {**a, **b}。実際、静かに失敗し、抽出時に空の辞書のように動作します。
Simon Streicher、2018

@SimonStreicher私はこれをテストしましたm = DotMap(); m.a = 2; m.b = 3; print('{a} {b}'.format(**m));が、期待通り2 3でした。動作するdict()が動作しないことが証明された壊れたケースがある場合はDotMap()、GitHubの[Issues]タブにコードを送信してください。
Chris Redford、

56

dictから派生して、andを実装__getattr____setattr__ます。

または、非常によく似たBunchを使用できます。

組み込みのdictクラスをモンキーパッチすることは不可能だと思います。


2
monkeypatchは正確にはどういう意味ですか?聞いたことはありますが使用していません。(このような初心者向けの質問をして申し訳ありませんが、私はまだプログラミングが苦手です(私は2年生だけです)。)
bodacydo

9
モンキーパッチは、Python(または任意の言語)の動的性を使用して、通常ソースコードで定義されるものを変更します。特に、クラスの作成後にクラスの定義を変更する場合に適用されます。
マイクグラハム

この機能を頻繁に使用している場合は、Bunchの速度に注意してください。私はそれをかなり頻繁に使用していました、そしてそれは私の要求時間の3分の1を費やしてしまいました。この詳細については、私の回答をご覧ください。
JayD3e 2015

22

ファブリックは本当に素晴らしい、最小限の実装です。ネストされたアクセスを可能にするためにそれを拡張するには、を使用できます。defaultdict結果は次のようになります。

from collections import defaultdict

class AttributeDict(defaultdict):
    def __init__(self):
        super(AttributeDict, self).__init__(AttributeDict)

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError(key)

    def __setattr__(self, key, value):
        self[key] = value

次のように使用します。

keys = AttributeDict()
keys.abc.xyz.x = 123
keys.abc.xyz.a.b.c = 234

それはのクーゲルの答えに少し詳しく説明「辞書から派生して、実施__getattr__して__setattr__」。今、あなたは方法を知っています!


1
あれは素晴らしい!
トーマスクリンガー

defaultdictを含めるのはいいですが、これは最初からdictを開始する場合にのみ機能するようです。既存の辞書を「dotdict」に再帰的に変換する必要がある場合。ここでは代替だdotdict既存の変換することができdict、再帰的にオブジェクト:gist.github.com/miku/...
ミク

19

私はこれを試しました:

class dotdict(dict):
    def __getattr__(self, name):
        return self[name]

あなたも試すことができ__getattribute__ます。

すべてのdictをdotdictのタイプで十分にできます。これをマルチレイヤーdictから初期化したい場合は、実装__init__も試してください。


おっと、@ Kugelの答えは似ています。
tdihp

1
tdihp、私はそれがより速く理解したので、あなたの答えがまだ好きです-それは実際のコードを持っています。
yigal 2014年

1
実際のコードの場合は+1。しかし、@ KugelによるBunchの使用に関する提案も非常に優れています。
Dannid 2014年

これを関数のdef docdict(name):前に置いてから埋め込むと便利です。`if isinstance(name、dict):return DotDict(name)return name `
Daniel

素晴らしい単純な例です。@ DanielMoskovichと同様に、ネストされたdictを簡単にチェーンできるようにこれを少し拡張しましたが、int、stringなどのリーフノードを正しく返します。見つからない場合はnullclass dotdict(dict): def __getattr__(self, name): if name not in self: return None elif type(self[name]) is dict: return JsonDot(self[name]) else: return self[name]
D Sievers

11

しないでください。Pythonでは属性へのアクセスとインデックス作成は別のものであり、同じように実行することは望ましくありません。namedtupleアクセス可能な属性を持つ必要があるものがある場合はクラス(おそらくによって作成されたもの)を作成し、[]表記法を使用してディクショナリからアイテムを取得します。


答えてくれてありがとう。しかし、私が今尋ねたこの質問を見てみましょう:stackoverflow.com/questions/2352252/… これは、Makoテンプレートの複雑なデータ構造にアクセスする.代わりに使用するのに良い考えのよう[]です。
bodacydo

2
この使用例を見ることができます。実際、ほんの数週間前にそれをしました。私の場合、ドット表記で属性にアクセスできるオブジェクトが必要でした。私はdictから単純に継承するのが非常に簡単であるため、すべてのdict機能が組み込まれていますが、このオブジェクトへのパブリックインターフェイスはドット表記を使用します(これは基本的に、一部の静的データへの読み取り専用インターフェイスです)。私のユーザーは、 'foo ["bar"]'よりも 'foo.bar'の方がはるかに満足しています。dictデータ型の機能を利用できてうれしいです。
Bryan Oakley、

10
Pythonスタイルはすでにご存じでしょう。つまり、dictの値が属性であると偽ってはいけません。それは悪い習慣です。たとえば、「items」、「get」、「pop」など、dictの既存の属性と同じ名前の値を保存する場合はどうでしょうか。おそらく混乱を招くものでしょう。やらないで!
Larry Hastings

5
おっと、 'items'、 'get'、 'pop'などの属性を忘れてしまいました。この重要な例をご提示いただきありがとうございます。
bodacydo

5
@Gabe、久しぶりですが... 「JSで十分」ではなく、「JSで恐ろしい」です。プロトタイプチェーン内の他の重要な属性と同じ名前のキー/属性を保存すると、面白くなります。
bgusach 14年

11

変更した辞書をピクルしたい場合は、上記の回答にいくつかの状態メソッドを追加する必要があります。

class DotDict(dict):
    """dot.notation access to dictionary attributes"""
    def __getattr__(self, attr):
        return self.get(attr)
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

    def __getstate__(self):
        return self

    def __setstate__(self, state):
        self.update(state)
        self.__dict__ = self

酸洗についてのコメントをありがとう。私はこのエラーに夢中になり、この問題が原因であることに気づきました!
Shagru

copy.deepcopyを使用した場合にも発生します。この追加が必要です。
user1363990 2017

簡略化:__getattr__ = dict.get
マルティノー

9

クーゲルの答えに基づいて、マイクグラハムの注意の言葉を考慮に入れて、ラッパーを作成するとどうなるでしょうか。

class DictWrap(object):
  """ Wrap an existing dict, or create a new one, and access with either dot 
    notation or key lookup.

    The attribute _data is reserved and stores the underlying dictionary.
    When using the += operator with create=True, the empty nested dict is 
    replaced with the operand, effectively creating a default dictionary
    of mixed types.

    args:
      d({}): Existing dict to wrap, an empty dict is created by default
      create(True): Create an empty, nested dict instead of raising a KeyError

    example:
      >>>dw = DictWrap({'pp':3})
      >>>dw.a.b += 2
      >>>dw.a.b += 2
      >>>dw.a['c'] += 'Hello'
      >>>dw.a['c'] += ' World'
      >>>dw.a.d
      >>>print dw._data
      {'a': {'c': 'Hello World', 'b': 4, 'd': {}}, 'pp': 3}

  """

  def __init__(self, d=None, create=True):
    if d is None:
      d = {}
    supr = super(DictWrap, self)  
    supr.__setattr__('_data', d)
    supr.__setattr__('__create', create)

  def __getattr__(self, name):
    try:
      value = self._data[name]
    except KeyError:
      if not super(DictWrap, self).__getattribute__('__create'):
        raise
      value = {}
      self._data[name] = value

    if hasattr(value, 'items'):
      create = super(DictWrap, self).__getattribute__('__create')
      return DictWrap(value, create)
    return value

  def __setattr__(self, name, value):
    self._data[name] = value  

  def __getitem__(self, key):
    try:
      value = self._data[key]
    except KeyError:
      if not super(DictWrap, self).__getattribute__('__create'):
        raise
      value = {}
      self._data[key] = value

    if hasattr(value, 'items'):
      create = super(DictWrap, self).__getattribute__('__create')
      return DictWrap(value, create)
    return value

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

  def __iadd__(self, other):
    if self._data:
      raise TypeError("A Nested dict will only be replaced if it's empty")
    else:
      return other

8

使用SimpleNamespace

>>> from types import SimpleNamespace   
>>> d = dict(x=[1, 2], y=['a', 'b'])
>>> ns = SimpleNamespace(**d)
>>> ns.x
[1, 2]
>>> ns
namespace(x=[1, 2], y=['a', 'b'])

1
このアプローチの方が効果的です。(JSONをファイルからロード)
GED

これはネストされた辞書を説明しますか?
門司

1
ネストされたDictをサポートしません。docs.python.org/3.3/library/types.html#types.SimpleNamespace
カーソン

6

私はムンクが好きで、ドットアクセスに加えて便利なオプションがたくさんあります。

ムンク輸入

temp_1 = {'person':{'fname': 'senthil'、 'lname': 'ramalingam'}}

dict_munch = munch.munchify(temp_1)

dict_munch.person.fname


6

私は最近同じことをする ' Box 'ライブラリに出くわしました。

インストールコマンド: pip install python-box

例:

from box import Box

mydict = {"key1":{"v1":0.375,
                    "v2":0.625},
          "key2":0.125,
          }
mydict = Box(mydict)

print(mydict.key1.v1)

私はそれがdotmapのような他の既存のライブラリよりも効果的であることがわかりました。

ライブラリと詳細へのリンク:https : //pypi.org/project/python-box/


5

__getattr__非常に単純なを使用して、Python 3.4.3で動作します

class myDict(dict):
    def __getattr__(self,val):
        return self[val]


blockBody=myDict()
blockBody['item1']=10000
blockBody['item2']="StackOverflow"
print(blockBody.item1)
print(blockBody.item2)

出力:

10000
StackOverflow

4

言語自体はこれをサポートしていませんが、時々これはまだ有用な要件です。Bunchレシピのほかに、ドット付き文字列を使用して辞書にアクセスできる小さなメソッドを記述することもできます。

def get_var(input_dict, accessor_string):
    """Gets data from a dictionary using a dotted accessor-string"""
    current_data = input_dict
    for chunk in accessor_string.split('.'):
        current_data = current_data.get(chunk, {})
    return current_data

これは次のようなものをサポートします:

>> test_dict = {'thing': {'spam': 12, 'foo': {'cheeze': 'bar'}}}
>> output = get_var(test_dict, 'thing.spam.foo.cheeze')
>> print output
'bar'
>>

4

epoolの答えに基づいて構築するために、このバージョンではドット演算子を介して内部のすべてのdictにアクセスできます。

foo = {
    "bar" : {
        "baz" : [ {"boo" : "hoo"} , {"baba" : "loo"} ]
    }
}

たとえば、をfoo.bar.baz[1].baba返します"loo"

class Map(dict):
    def __init__(self, *args, **kwargs):
        super(Map, self).__init__(*args, **kwargs)
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    if isinstance(v, dict):
                        v = Map(v)
                    if isinstance(v, list):
                        self.__convert(v)
                    self[k] = v

        if kwargs:
            for k, v in kwargs.iteritems():
                if isinstance(v, dict):
                    v = Map(v)
                elif isinstance(v, list):
                    self.__convert(v)
                self[k] = v

    def __convert(self, v):
        for elem in xrange(0, len(v)):
            if isinstance(v[elem], dict):
                v[elem] = Map(v[elem])
            elif isinstance(v[elem], list):
                self.__convert(v[elem])

    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(Map, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(Map, self).__delitem__(key)
        del self.__dict__[key]

1
Pythonの3:交換するiteritems()items()してxrange()range()
sasawatc

3
def dict_to_object(dick):
    # http://stackoverflow.com/a/1305663/968442

    class Struct:
        def __init__(self, **entries):
            self.__dict__.update(entries)

    return Struct(**dick)

これを永続的dictにオブジェクトに変換することを決定した場合、これを行う必要があります。アクセスの直前に使い捨てオブジェクトを作成できます。

d = dict_to_object(d)

def attr(** kwargs):o = lambda:None o .__ dict __。update(** kwargs)return o
throws_exceptions_at_you

2

AttrDictの両方を試してしまいましたBunchのしまいましたライブラリは、それらが私の使用のために遅くする方法であることがわかりました。友人と私が調べたところ、これらのライブラリを作成する主な方法の結果、ライブラリはネストされたオブジェクトを積極的に再帰し、辞書オブジェクトのコピーを全体に作成することがわかりました。これを念頭に置いて、2つの重要な変更を行いました。1)属性を遅延ロードしました2)辞書オブジェクトのコピーを作成する代わりに、軽量プロキシオブジェクトのコピーを作成します。これが最終的な実装です。このコードを使用すると、パフォーマンスが大幅に向上します。AttrDictまたはBunchを使用する場合、これらの2つのライブラリーだけで、要求時間のそれぞれ1/2および1/3を消費しました(what !?)。このコードは、その時間をほとんど(0.5msの範囲のどこか)に減らしました。これはもちろんニーズによって異なりますが、この機能をコードでかなり使用している場合は、

class DictProxy(object):
    def __init__(self, obj):
        self.obj = obj

    def __getitem__(self, key):
        return wrap(self.obj[key])

    def __getattr__(self, key):
        try:
            return wrap(getattr(self.obj, key))
        except AttributeError:
            try:
                return self[key]
            except KeyError:
                raise AttributeError(key)

    # you probably also want to proxy important list properties along like
    # items(), iteritems() and __len__

class ListProxy(object):
    def __init__(self, obj):
        self.obj = obj

    def __getitem__(self, key):
        return wrap(self.obj[key])

    # you probably also want to proxy important list properties along like
    # __iter__ and __len__

def wrap(value):
    if isinstance(value, dict):
        return DictProxy(value)
    if isinstance(value, (tuple, list)):
        return ListProxy(value)
    return value

https://stackoverflow.com/users/704327/michael-merickelによる元の実装をここで参照してください

もう1つ注意すべき点は、この実装は非常に単純であり、必要なすべてのメソッドを実装していないことです。必要に応じて、DictProxyまたはListProxyオブジェクトにそれらを書き込む必要があります。


0

私は自分の解決策をリングに投げ込みたいです:

https://github.com/skorokithakis/jsane

これにより、JSONを解析してアクセス可能なものにすることができますwith.attribute.lookups.like.this.r()。これは、作業を開始する前にこの答えを見たことがないためです。


Pythonはいくつかの厄介な単純な設計ミスを犯しKeyErrorています。発生はその1つです。存在しないキーにアクセスするNoneと、JSの動作と同様に返されます。私は、読み書き両方のautovivificationの大ファンです。あなたの図書館は理想に最も近い。
ニーム、

0

OPの質問への直接の回答ではありませんが、一部の人に触発され、おそらく役に立つでしょう。内部を使用してオブジェクトベースのソリューションを作成しました__dict__(決して最適化されたコードではありません)。

payload = {
    "name": "John",
    "location": {
        "lat": 53.12312312,
        "long": 43.21345112
    },
    "numbers": [
        {
            "role": "home",
            "number": "070-12345678"
        },
        {
            "role": "office",
            "number": "070-12345679"
        }
    ]
}


class Map(object):
    """
    Dot style access to object members, access raw values
    with an underscore e.g.

    class Foo(Map):
        def foo(self):
            return self.get('foo') + 'bar'

    obj = Foo(**{'foo': 'foo'})

    obj.foo => 'foobar'
    obj._foo => 'foo'

    """

    def __init__(self, *args, **kwargs):
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    self.__dict__[k] = v
                    self.__dict__['_' + k] = v

        if kwargs:
            for k, v in kwargs.iteritems():
                self.__dict__[k] = v
                self.__dict__['_' + k] = v

    def __getattribute__(self, attr):
        if hasattr(self, 'get_' + attr):
            return object.__getattribute__(self, 'get_' + attr)()
        else:
            return object.__getattribute__(self, attr)

    def get(self, key):
        try:
            return self.__dict__.get('get_' + key)()
        except (AttributeError, TypeError):
            return self.__dict__.get(key)

    def __repr__(self):
        return u"<{name} object>".format(
            name=self.__class__.__name__
        )


class Number(Map):
    def get_role(self):
        return self.get('role')

    def get_number(self):
        return self.get('number')


class Location(Map):
    def get_latitude(self):
        return self.get('lat') + 1

    def get_longitude(self):
        return self.get('long') + 1


class Item(Map):
    def get_name(self):
        return self.get('name') + " Doe"

    def get_location(self):
        return Location(**self.get('location'))

    def get_numbers(self):
        return [Number(**n) for n in self.get('numbers')]


# Tests

obj = Item({'foo': 'bar'}, **payload)

assert type(obj) == Item
assert obj._name == "John"
assert obj.name == "John Doe"
assert type(obj.location) == Location
assert obj.location._lat == 53.12312312
assert obj.location._long == 43.21345112
assert obj.location.latitude == 54.12312312
assert obj.location.longitude == 44.21345112

for n in obj.numbers:
    assert type(n) == Number
    if n.role == 'home':
        assert n.number == "070-12345678"
    if n.role == 'office':
        assert n.number == "070-12345679"

0

ドットアクセス(配列アクセスではない)を取得する簡単な方法の1つは、Pythonでプレーンオブジェクトを使用することです。このような:

class YourObject:
    def __init__(self, *args, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

...次のように使用します。

>>> obj = YourObject(key="value")
>>> print(obj.key)
"value"

... dictに変換するには:

>>> print(obj.__dict__)
{"key": "value"}

0

このソリューションは、OPがネストされたディクショナリに一貫した方法でアクセスするための要件に対処するためにepoolが提供するソリューションを改良したものです。epoolによるソリューションでは、ネストされた辞書にアクセスできませんでした。

class YAMLobj(dict):
    def __init__(self, args):
        super(YAMLobj, self).__init__(args)
        if isinstance(args, dict):
            for k, v in args.iteritems():
                if not isinstance(v, dict):
                    self[k] = v
                else:
                    self.__setattr__(k, YAMLobj(v))


    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(YAMLobj, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(YAMLobj, self).__delitem__(key)
        del self.__dict__[key]

このクラスを使用すると、次のようなことができますA.B.C.D


0

これはネストされたdictでも機能し、後で追加されるdictが同じように動作することを確認します。

class DotDict(dict):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Recursively turn nested dicts into DotDicts
        for key, value in self.items():
            if type(value) is dict:
                self[key] = DotDict(value)

    def __setitem__(self, key, item):
        if type(item) is dict:
            item = DotDict(item)
        super().__setitem__(key, item)

    __setattr__ = __setitem__
    __getattr__ = dict.__getitem__

0

@ derek73の答えは非常にきちんとしていますが、漬けたり、(深い)コピーしたりすることはできませんNone。以下のコードはこれを修正します。

編集:まったく同じ点を取り上げている上記の回答はありませんでした(賛成)。参考までにここに答えを残しておきます。

class dotdict(dict):
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            raise AttributeError(name)

-1

デリケートなソリューション

class DotDict(dict):

    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

    def __getattr__(self, key):

        def typer(candidate):
            if isinstance(candidate, dict):
                return DotDict(candidate)

            if isinstance(candidate, str):  # iterable but no need to iter
                return candidate

            try:  # other iterable are processed as list
                return [typer(item) for item in candidate]
            except TypeError:
                return candidate

            return candidate

        return typer(dict.get(self, key))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.