使用“in”匹配数组中 Python 对象的属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using 'in' to match an attribute of Python objects in an array
提问by Brendan
I don't remember whether I was dreaming or not but I seem to recall there being a function which allowed something like,
我不记得我是否在做梦,但我似乎记得有一个功能允许类似的东西,
foo in iter_attr(array of python objects, attribute name)
I've looked over the docs but this kind of thing doesn't fall under any obvious listed headers
我查看了文档,但这种事情不属于任何明显列出的标题
采纳答案by Will Harris
Using a list comprehension would build a temporary list, which could eat all your memory if the sequence being searched is large. Even if the sequence is not large, building the list means iterating over the whole of the sequence before in
could start its search.
使用列表推导会构建一个临时列表,如果要搜索的序列很大,它可能会占用您所有的内存。即使序列不大,构建列表也意味着在in
开始搜索之前迭代整个序列。
The temporary list can be avoiding by using a generator expression:
可以使用生成器表达式避免临时列表:
foo = 12
foo in (obj.id for obj in bar)
Now, as long as obj.id == 12
near the start of bar
, the search will be fast, even if bar
is infinitely long.
现在,只要obj.id == 12
接近 的开始bar
,搜索就会很快,即使bar
是无限长的。
As @Matt suggested, it's a good idea to use hasattr
if any of the objects in bar
can be missing an id
attribute:
正如@Matt 所建议的,hasattr
如果 中的任何对象bar
可能缺少id
属性,那么使用它是一个好主意:
foo = 12
foo in (obj.id for obj in bar if hasattr(obj, 'id'))
回答by Matt
Are you looking to get a list of objects that have a certain attribute? If so, a list comprehensionis the right way to do this.
您是否希望获得具有特定属性的对象列表?如果是这样,列表理解是正确的方法。
result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]
回答by dwestbrook
you could always write one yourself:
你总是可以自己写一个:
def iterattr(iterator, attributename):
for obj in iterator:
yield getattr(obj, attributename)
will work with anything that iterates, be it a tuple, list, or whatever.
将适用于任何迭代的东西,无论是元组、列表还是其他任何东西。
I love python, it makes stuff like this very simple and no more of a hassle than neccessary, and in use stuff like this is hugely elegant.
我喜欢 python,它使这样的东西变得非常简单,而且没有必要,而且在使用中这样的东西非常优雅。
回答by saalon
No, you were not dreaming. Python has a pretty excellent list comprehension system that lets you manipulate lists pretty elegantly, and depending on exactly what you want to accomplish, this can be done a couple of ways. In essence, what you're doing is saying "For item in list if criteria.matches", and from that you can just iterate through the results or dump the results into a new list.
不,你不是在做梦。Python 有一个非常出色的列表理解系统,可以让您非常优雅地操作列表,并且可以通过多种方式完成,具体取决于您想要完成的任务。从本质上讲,您正在做的是说“对于列表中的项目,如果criteria.matches”,然后您就可以遍历结果或将结果转储到新列表中。
I'm going to crib an example from Dive Into Pythonhere, because it's pretty elegant and they're smarter than I am. Here they're getting a list of files in a directory, then filtering the list for all files that match a regular expression criteria.
我将在这里引用 Dive Into Python 中的一个示例,因为它非常优雅,而且它们比我更聪明。在这里,他们获取目录中的文件列表,然后过滤列表以查找与正则表达式条件匹配的所有文件。
files = os.listdir(path) test = re.compile("test\.py$", re.IGNORECASE) files = [f for f in files if test.search(f)]
files = os.listdir(path) test = re.compile("test\.py$", re.IGNORECASE) files = [f for f in files if test.search(f)]
You could do this without regular expressions, for your example, for anything where your expression at the end returns true for a match. There are other options like using the filter() function, but if I were going to choose, I'd go with this.
对于您的示例,您可以在没有正则表达式的情况下执行此操作,对于任何在末尾的表达式为匹配项返回 true 的内容。还有其他选项,比如使用 filter() 函数,但如果我要选择,我会选择这个。
Eric Sipple
埃里克·西普尔
回答by shang
The function you are thinking of is probably operator.attrgettter
. For example, to get a list that contains the value of each object's "id" attribute:
您正在考虑的功能可能是operator.attrgettter
. 例如,要获取包含每个对象的“id”属性值的列表:
import operator
ids = map(operator.attrgetter("id"), bar)
If you want to check whether the list contains an object with an id == 12, then a neat and efficient (i.e. doesn't iterate the whole list unnecessarily) way to do it is:
如果您想检查列表是否包含一个 id == 12 的对象,那么一种简洁高效(即不会不必要地迭代整个列表)的方法是:
any(obj.id == 12 for obj in bar)
If you want to use 'in' with attrgetter, while still retaining lazy iteration of the list:
如果您想将 'in' 与 attrgetter 一起使用,同时仍保留列表的惰性迭代:
import operator,itertools
foo = 12
foo in itertools.imap(operator.attrgetter("id"), bar)
回答by Brendan
What I was thinking of can be achieved using list comprehensions, but I thought that there was a function that did this in a slightly neater way.
使用列表推导式可以实现我的想法,但我认为有一个函数可以以稍微简洁的方式完成此操作。
i.e. 'bar' is a list of objects, all of which have the attribute 'id'
即 'bar' 是一个对象列表,所有这些对象都具有属性 'id'
The mythical functional way:
神话般的功能方式:
foo = 12
foo in iter_attr(bar, 'id')
The list comprehension way:
列表理解方式:
foo = 12
foo in [obj.id for obj in bar]
In retrospect the list comprehension way is pretty neat anyway.
回想起来,无论如何,列表理解方式非常简洁。
回答by Jason Baker
If you plan on searching anything of remotely decent size, your best bet is going to be to use a dictionary or a set. Otherwise, you basically have to iterate through every element of the iterator until you get to the one you want.
如果您打算搜索任何大小合适的东西,最好的办法是使用字典或集合。否则,您基本上必须遍历迭代器的每个元素,直到找到您想要的元素。
If this isn't necessarily performance sensitive code, then the list comprehension way should work. But note that it is fairly inefficient because it goes over every element of the iterator and then goes BACK over it again until it finds what it wants.
如果这不一定是性能敏感的代码,那么列表理解方式应该有效。但请注意,它的效率相当低,因为它遍历迭代器的每个元素,然后再次返回,直到找到它想要的元素。
Remember, python has one of the most efficient hashing algorithms around. Use it to your advantage.
请记住,python 拥有最高效的散列算法之一。充分利用它。
回答by akdom
I think:
我认为:
#!/bin/python
bar in dict(Foo)
Is what you are thinking of. When trying to see if a certain key exists within a dictionary in python (python's version of a hash table) there are two ways to check. First is the has_key()
method attached to the dictionary and second is the example given above. It will return a boolean value.
是你在想什么。当试图查看 Python 的字典中是否存在某个键时(哈希表的 Python 版本),有两种方法可以检查。第一个是has_key()
附在字典上的方法,第二个是上面给出的例子。它将返回一个布尔值。
That should answer your question.
那应该回答你的问题。
And now a little off topic to tie this in to the list comprehensionanswer previously given (for a bit more clarity). List Comprehensionsconstruct a list from a basic for loopwith modifiers. As an example (to clarify slightly), a way to use the in dict
language construct in a list comprehension:
现在有点偏离主题,将其与之前给出的列表理解答案联系起来(为了更清楚一点)。 列表推导式从带有修饰符的基本for 循环构造一个列表。作为一个例子(稍微澄清一下),一种in dict
在列表理解中使用语言结构的方法:
Say you have a two dimensional dictionary foo
and you only want the second dimension dictionaries which contain the key bar
. A relatively straightforward way to do so would be to use a list comprehensionwith a conditional as follows:
假设你有一个二维字典foo
,你只想要包含 key 的第二维字典bar
。一种相对直接的方法是使用带有条件的列表推导式,如下所示:
#!/bin/python
baz = dict([(key, value) for key, value in foo if bar in value])
Note the if bar in value
at the end of the statement**, this is a modifying clause which tells the list comprehensionto only keep those key-value pairs which meet the conditional.** In this case baz
is a new dictionary which contains only the dictionaries from foo which contain bar (Hopefully I didn't miss anything in that code example... you may have to take a look at the list comprehension documentation found in docs.python.org tutorialsand at secnetix.de, both sites are good references if you have questions in the future.).
注意if bar in value
语句的末尾**,这是一个修改子句,它告诉列表推导式只保留那些满足条件的键值对。** 在这种情况下baz
是一个新字典,它只包含来自 foo 的字典其中包含 bar(希望我没有遗漏该代码示例中的任何内容……您可能需要查看docs.python.org 教程和secnetix.de中的列表理解文档,如果你以后有问题。)