我确信有一个关于我正在寻找的术语,或者如果没有,有一个很好的理由我想要做的事实上是愚蠢的。
但无论如何。我想知道是否有(准)内置方法来查找某个属性设置为某个值的类实例。
一个例子:
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中,如果不存在,那么必定有一个非常好的理由为什么它不存在。换句话说,我在这里尝试做的事情可以用更好的方式完成。
(当然,我不是在寻找一种方法来设定一个值。上面只是我想要寻找的构造的一个例子。)
答案 0 :(得分:4)
使用过滤器:
filter(lambda obj: obj.value == 1, [a, b])
过滤器将返回符合您指定要求的对象列表。文档:http://docs.python.org/library/functions.html#filter
基本上,filter(fn, list)
会对list
进行迭代,并对每个项目应用fn
。它收集fn
返回true的所有项目,然后将其放入列表中,然后返回它们。
注意:过滤器将始终返回列表,即使只有一个匹配的对象。因此,如果您只想返回匹配的第一个实例,则必须执行以下操作:
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
。
答案 1 :(得分: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)
后者的优点是不会进行大量的函数调用,所以可能会稍快一些,尽管差异可能很小。