我不记得我是不是在做梦,但我似乎记得有一个功能允许这样的事情,
foo in iter_attr(array of python objects, attribute name)
我查看了文档,但这种事情不属于任何明显列出的标题
答案 0 :(得分:41)
使用列表推导会构建一个临时列表,如果搜索的序列很大,可能会占用所有内存。即使序列不大,构建列表意味着在in
开始搜索之前迭代整个序列。
使用生成器表达式可以避免临时列表:
foo = 12
foo in (obj.id for obj in bar)
现在,只要在obj.id == 12
开头附近bar
,即使bar
无限长,搜索也会很快。
正如@Matt建议的那样,如果hasattr
中的任何对象可能缺少bar
属性,则最好使用id
:
foo = 12
foo in (obj.id for obj in bar if hasattr(obj, 'id'))
答案 1 :(得分:12)
您是否希望获得具有特定属性的对象列表?如果是这样,list comprehension是正确的方法。
result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]
答案 2 :(得分:10)
你总是可以自己写一个:
def iterattr(iterator, attributename):
for obj in iterator:
yield getattr(obj, attributename)
将适用于迭代的任何内容,无论是元组,列表还是其他任何内容。
我喜欢python,它使这样的东西变得非常简单,不再需要麻烦,而且在使用中这样的东西非常优雅。
答案 3 :(得分:7)
不,你不是在做梦。 Python有一个非常出色的列表理解系统,可以让你非常优雅地操作列表,并且根据你想要完成的内容,这可以通过几种方式完成。从本质上讲,您正在做的是“如果条件匹配,则列表中的项目”,并且您可以通过迭代结果或将结果转储到新列表中。
我要在Dive Into Python处举一个例子,因为它非常优雅,而且比我更聪明。在这里,他们获取目录中的文件列表,然后过滤列表以查找与正则表达式条件匹配的所有文件。
files = os.listdir(path) test = re.compile("test\.py$", re.IGNORECASE) files = [f for f in files if test.search(f)]
对于您的示例,您可以在没有正则表达式的情况下执行此操作,对于您的结尾处的表达式为匹配返回true的任何内容。还有其他选项,比如使用filter()函数,但如果我要选择,我会选择这个。
Eric Sipple
答案 4 :(得分:6)
您正在考虑的功能可能是operator.attrgettter
。例如,要获取包含每个对象的“id”属性值的列表:
import operator
ids = map(operator.attrgetter("id"), bar)
如果要检查列表是否包含id == 12的对象,那么整洁有效(即不会不必要地迭代整个列表)的方法是:
any(obj.id == 12 for obj in bar)
如果你想在attrgetter中使用'in',同时仍然保留列表的延迟迭代:
import operator,itertools
foo = 12
foo in itertools.imap(operator.attrgetter("id"), bar)
答案 5 :(得分:5)
我想到的是可以使用列表推导来实现,但我认为有一个函数以稍微更简洁的方式做到了。
即。 'bar'是一个对象列表,所有对象都具有属性'id'
神话般的功能方式:
foo = 12
foo in iter_attr(bar, 'id')
列表理解方式:
foo = 12
foo in [obj.id for obj in bar]
回想起来,无论如何,列表理解方式非常简洁。
答案 6 :(得分:3)
如果你打算搜索任何大小合适的东西,你最好的选择是使用字典或集合。否则,你基本上必须遍历迭代器的每个元素,直到你得到你想要的那个。
如果这不一定是性能敏感的代码,那么列表理解方式应该有效。但请注意,它是相当低效的,因为它遍历迭代器的每个元素,然后再次返回它,直到找到它想要的为止。
请记住,python有一种最有效的哈希算法。使用它对您有利。
答案 7 :(得分:0)
我想:
#!/bin/python
bar in dict(Foo)
你在想什么。当试图查看python(python的哈希表版本)中的字典中是否存在某个键时,有两种方法可以检查。首先是附加到字典的 has_key()
方法,其次是上面给出的示例。它将返回一个布尔值。
那应该回答你的问题。
现在有点偏离主题将此与之前给出的列表理解答案联系起来(为了更加清晰)。 List Comprehensions 使用修饰符从基本的 for循环构造一个列表。作为示例(稍微澄清),在列表理解中使用in dict
语言构造的方法:
假设您有一个二维字典 foo
,并且您只需要包含密钥 bar
的第二维字典。一个相对简单的方法是使用带有条件的列表理解,如下所示:
#!/bin/python
baz = dict([(key, value) for key, value in foo if bar in value])
请注意语句末尾的 if bar in value
**,这是一个修改子句,告诉列表理解只保留这些键值满足条件的对。**在这种情况下, baz
是一个新词典,其中只包含foo中包含bar的词典(希望我在该代码示例中没有遗漏任何内容。 ..您可能需要查看docs.python.org tutorials和secnetix.de中的列表理解文档,如果您将来有疑问,这两个站点都是很好的参考。)。