问题描述
在for循环上下文中使用列表理解或in
关键字时,即:
When using list comprehension or the in
keyword in a for loop context, i.e:
for o in X:
do_something_with(o)
或
l=[o for o in X]
-
in
背后的机制如何工作? - 它调用
X
中的哪些函数\方法? - 如果
X
可以遵循多种方法,那么优先级是多少? - 如何编写高效的
X
,以便快速理解列表? - How does the mechanism behind
in
works? - Which functions\methods within
X
does it call? - If
X
can comply to more than one method, what's the precedence? - How to write an efficient
X
, so that list comprehension will be quick?
推荐答案
答案是正确的.
for
在for循环和列表推导中都在X
上调用iter()
.如果X
具有__iter__
方法或__getitem__
方法,则iter()
将返回可迭代.如果两者都实现,则使用__iter__
.如果没有,您将得到TypeError: 'Nothing' object is not iterable
.
for
, both in for loops and list comprehensions, calls iter()
on X
. iter()
will return an iterable if X
either has an __iter__
method or a __getitem__
method. If it implements both, __iter__
is used. If it has neither you get TypeError: 'Nothing' object is not iterable
.
这实现了__getitem__
:
class GetItem(object):
def __init__(self, data):
self.data = data
def __getitem__(self, x):
return self.data[x]
用法:
>>> data = range(10)
>>> print [x*x for x in GetItem(data)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
这是实现__iter__
的示例:
class TheIterator(object):
def __init__(self, data):
self.data = data
self.index = -1
# Note: In Python 3 this is called __next__
def next(self):
self.index += 1
try:
return self.data[self.index]
except IndexError:
raise StopIteration
def __iter__(self):
return self
class Iter(object):
def __init__(self, data):
self.data = data
def __iter__(self):
return TheIterator(data)
用法:
>>> data = range(10)
>>> print [x*x for x in Iter(data)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
如您所见,您既需要实现一个迭代器,又需要返回迭代器的__iter__
.
As you see you need both to implement an iterator, and __iter__
that returns the iterator.
您可以将它们组合在一起:
You can combine them:
class CombinedIter(object):
def __init__(self, data):
self.data = data
def __iter__(self):
self.index = -1
return self
def next(self):
self.index += 1
try:
return self.data[self.index]
except IndexError:
raise StopIteration
用法:
>>> well, you get it, it's all the same...
但是,一次只能有一个迭代器.好的,在这种情况下,您可以这样做:
But then you can only have one iterator going at once.OK, in this case you could just do this:
class CheatIter(object):
def __init__(self, data):
self.data = data
def __iter__(self):
return iter(self.data)
但这是作弊,因为您只是在重用list
的__iter__
方法.一种更简单的方法是使用yield,并将__iter__
用作生成器:
But that's cheating because you are just reusing the __iter__
method of list
.An easier way is to use yield, and make __iter__
into a generator:
class Generator(object):
def __init__(self, data):
self.data = data
def __iter__(self):
for x in self.data:
yield x
这是我推荐的方式.简单高效.
这篇关于Python:列表理解背后的机制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!