也许我太晚了。
我有一个对象是字典周围的薄包装器。它将伪装成字典中任何键的属性,如果引用了不存在的键,则返回None。
我想只获得三个可能键的唯一“真实”值。 (不是没有)。对象可能没有一个或多个键。或者,它可能在两个或三个键中具有相同的值。
这段代码符合我的要求:
set(getattr(obj, field) for field in ['field1', 'field2', 'field3'] if getattr(obj, field))
我只是不喜欢两次重复getattr()的样子。我觉得我忽视了一个明显更好的方法。
答案 0 :(得分:4)
您可以在之后过滤出None
值:
set(filter(bool, [getattr(obj, field) for field in ['field1', 'field2', 'field3']]))
或者你可以忘掉这个对象。这可能是我这样做的方式:
a_dict = {'key1': 1, 'key2': 2, 'key3missing': 3}
print set([a_dict[key] for key in ['key1','key2','key3'] if key in a_dict])
# prints: set([1, 2])
答案 1 :(得分:3)
如果您的瘦包装器返回默认None
:
s = set(getattr(obj, field) for field in ['field1', 'field2', 'field3']) - {None}
另一种可能性:
s = set(filter(None, (getattr(obj, field) for field in ['field1', 'field2', 'field3']))
答案 2 :(得分:3)
另一种使用getattr默认值:
set(x for x in getattr(obj, field, None) for field in ['field1', 'field2', 'field3'] if x)
修改强>
这里是向你展示这个功能背后的逻辑 - 并说明为什么我认为它可能比其他一些解决方案更好(我可能是错的 - 但是嘿 - 生活就是从错误中学习)
obj = Your_Object
fields = ['field1', 'field2', 'field3']
def get_set(obj, fields):
result = []
for field in fields:
x = getattr(obj, field, None)
if x:
result.append(x)
return set(result)
如您所见,只有一个循环,getattr()
仅为每个字段调用一次。并且只有“truthy”值被添加到结果中。我认为这比获得所有结果更有效,然后在以后删除“非真实”值。但如果我错了,请纠正我。干杯。
答案 3 :(得分:1)
类似的东西:
from operator import attrgetter
class DictWrapper(object):
def __init__(self, d):
self.d = d
def __repr__(self):
return repr(self.d)
def __getattr__(self, name):
return self.d.get(name)
def truthy(self, *keys):
values = attrgetter(*keys)(self)
if not isinstance(values, tuple):
values = (values,)
return filter(None, set(values))
dw = DictWrapper({'x': 3, 'y': None, 'z': 'zebra'})
dw.truthy('x', 'y' ,'z', 'bob')
# [3, 'zebra']
dw.truthy('x')
# [3]
dw.truthy('y')
# []