获取某属性值为特定值的类实例

1 投票
2 回答
746 浏览
提问于 2025-04-17 05:36

我相信我在找的这个东西一定有个专门的名字,如果没有,那也一定有很好的理由说明我想做的事情其实是个傻事。

不过无论如何,我在想有没有一种(半)内置的方法,可以找到某个类的实例,并且这个实例的某个属性被设置为特定的值。

举个例子:

class Klass(object):
    def __init__(self, value):
        self.value = value
    def square_value(self):
        return self.value * self.value

 >>> a = Klass(1)
 >>> b = Klass(2)
 >>> instance = find_instance([a, b], value=1)
 >>> instance.square_value()
 1
 >>> instance = find_instance([a, b], value=2)
 >>> instance.square_value()
 4

我知道我可以写一个函数,去遍历所有的Klass实例,然后返回那些属性值符合要求的实例。但另一方面,我觉得这种功能应该在Python里已经存在了,如果没有,那一定有很好的理由说明它不应该存在。换句话说,我在这里想做的事情,可能有更好的方法来实现。

(当然,我并不是在找一种方法来计算平方值。上面的例子只是我想寻找的构造的一个示例。)

2 个回答

2

如果你只想找到一个匹配的实例,Ord的答案有一个更高效的版本,代码如下:

def find_instance(fn, objs):
    all_matches = (o for o in objs if fn(objs))
    return next(all_matches, None)

instance = find_instance(lambda x: x.value == 1, [a, b])

这个方法会在找到第一个匹配项后立即停止搜索(如果你的测试函数比较耗时或者列表很大,这样做很不错),如果没有找到匹配项,就会返回None

需要注意的是,next这个函数是在Python 2.6版本中新增的;在更早的版本中,我记得你需要这样做:

try:
   return all_matches.next()
except StopIteration:
   return None

当然,如果你只是想做一次,你可以用一行代码来实现:

instance = next((o for o in [a, b] if o.value == 1), None)

后者的好处是不会进行很多函数调用,所以可能会稍微快一点,尽管这个速度差别可能微不足道。

4

使用过滤器:

filter(lambda obj: obj.value == 1, [a, b])

过滤器会返回一个符合你指定条件的对象列表。文档链接:http://docs.python.org/library/functions.html#filter

简单来说,filter(fn, list) 会遍历 list 中的每一个项目,然后对每个项目应用 fn 这个函数。它会把所有 fn 返回为真的项目收集起来,放进一个列表中,然后返回这个列表。

注意:过滤器总是会返回一个列表,即使只有一个对象符合条件。所以如果你只想返回第一个符合条件的对象,你需要做一些额外的操作,比如:

def find_instance(fn, objs):
    all_matches = filter(fn, objs)
    if len(all_matches) == 0:
        return False # no matches
    else:
        return all_matches[0]

或者,更好的方法是:

def find_instance(fn, objs):
    all_matches = filter(fn, objs)
    return len(all_matches) > 0 and all_matches[0] # uses the fact that 'and' returns its second argument if its first argument evaluates to True. 

然后,你可以这样调用这个函数:

instance = find_instance(lambda x: x.value == 1, [a, b])

这样,instance 就会是 a

撰写回答