我正在处理其属性有时候列出的类,其元素可以是字典或具有属性的其他嵌套对象等。我想执行一些切片,因为我对python的掌握只能让人感觉非常不具有Pythonic。
我的最小代码如下:
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方式是列表理解a la:
[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'方法?
更新: 我一直在阅读有关重载列表的内容。显然,人们可能会混淆 getitem 方法,该方法用于dict的列表和键的indeces。也许是一个迭代列表成员的自定义类。这开始听起来很人为......
答案 0 :(得分: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
作为DictItems
的值。 get_items
操作以递归方式应用。