2

也许我只是起得太晚了。

我有一个对象是字典周围的薄包装器。它将假装对字典中的任何键都有一个属性,如果引用了不存在的键,则返回 None 。

我只想取回三个可能键的唯一“真实”值。(不是无)。对象可能没有一个或多个键。或者,它可能在两个或三个键中具有相同的值。

这段代码做我想要的:

set(getattr(obj, field) for field in ['field1', 'field2', 'field3'] if getattr(obj, field))

我只是不喜欢重复 getattr() 两次的样子。我觉得我忽略了一个明显更好的方法来做到这一点。

4

4 回答 4

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])
于 2012-09-12T09:01:42.287 回答
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']))
于 2012-09-12T08:59:12.443 回答
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)

如您所见,只有 1 个循环,并且getattr()每个字段只调用一次。并且仅将“真实”值添加到结果中。我认为这比获取所有结果然后稍后删除“非真实”值更有效。但如果我错了,请纠正我。干杯。

于 2012-09-12T09:42:58.707 回答
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')
# []
于 2012-09-12T10:12:38.553 回答