0

私は、属性が辞書であることがあるリストであるクラスや、属性などを含むネストされたオブジェクトを扱っています。Pythonを理解することで、Pythonが非常に非現実的であると感じるものでのみ実行できるスライスを実行したいと思います。

私の最小限のコードは次のようになります。

class X(object):
    def __init__(self):
       self.a = []

x=X()
x.a.append({'key1':'v1'})
x.a.append({'key1':'v2'})
x.a.append({'key1':'v3'})

# this works as desired
x.a[0]['key1'] # 'v1'

ネストされたディクショナリのキーへのアクセスを実行したいのですが、そのディクショナリを含むリストのすべての要素に対してその呼び出しを行います。これを行うための標準的なPythonの方法は、リスト内包表記です。

[v['key1'] for v in x.a]

ただし、私の最小限の例では、実際のシナリオでのネストの全範囲を完全に伝えることはできません。aクラスの属性リストにXは、オブジェクトが含まれている可能性があります。その属性はオブジェクトであり、その属性は、反復中にキーを選択する辞書です。外側のリスト。

# I would like something like
useful_list = x.a[:]['key1'] # TypeError: list indices must be integers, not str
# or even better
cool_list = where(x.a[:]['key1'] == 'v2') # same TypeError

すべての興味深いキーを理解するリストを開始すると、すぐにすべてのPythonicに見えなくなります。これを行うための良い方法はありますか、それともリストと辞書キーの考えられるすべての組み合わせに対して「getter」メソッドをコーディングする必要がありますか?

更新:私はリストのオーバーロードについて読んでいます。どうやら、リストのインデックスとdictのキーに使用されるgetitemメソッドを台無しにすることができます。たぶん、リストメンバーを反復処理するカスタムクラスです。これは不自然に聞こえ始めています...

4

1 に答える 1

2

したがって、異なる型に対して異なることを意味し、再帰的に定義される操作を使用して、階層構造を作成する必要があります。救助へのポリモーフィズム。

__getitem__以下の代わりにオーバーライドすることもできますget_itemsが、あなたの場合、あいまいさのリスクを避けるために非組み込み操作を定義する方が良いかもしれません。それは本当にあなた次第です。

class ItemsInterface(object):
    def get_items(self, key):
        raise NotImplementedError

class DictItems(ItemsInterface, dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
    def get_items(self, key):
        res = self[key]
        # apply recursively
        try:
            res = res.get_items(key)
        except AttributeError:
            pass
        return res

class ListItems(ItemsInterface, list):
    def __init__(self, *args, **kwargs):
        list.__init__(self, *args, **kwargs)
    def get_items(self, key):
        return [ x.get_items(key) for x in self ]

x = ListItems()
x.append(DictItems({'key1':'v1'}))
x.append(DictItems({'key1':'v2'}))
x.append(DictItems({'key1':'v3'}))
y = DictItems({'key1':'v999'})
x.append(ListItems([ y ]))
x.get_items('key1')
=> ['v1', 'v2', 'v3', ['v999']]

もちろん、この解決策はまさにあなたが必要としているものではないかもしれません (キーが見つからない場合に何をすべきかを説明していないなど) が、ニーズに合わせて簡単に変更できます。

このソリューションはListItems、 の値としてもサポートしていますDictItemsget_items操作は再帰的に適用されます。

于 2013-03-10T07:08:15.070 に答える