Python:列表理解背后的机制

Ada*_*tan 6 python implementation list-comprehension language-implementation

in在for循环上下文中使用list comprehension或关键字时,即:

for o in X:
    do_something_with(o)
Run Code Online (Sandbox Code Playgroud)

要么

l=[o for o in X]
Run Code Online (Sandbox Code Playgroud)
  • 背后的机制如何in运作?
  • X它调用哪些函数\方法?
  • 如果X能够遵循多种方法,那么优先级是什么?
  • 如何写出高效的X,这样列表理解会很快?

Len*_*bro 10

,afaik,完整和正确的答案.

for,无论是在for循环和list解析,呼吁iter()X.iter()如果X__iter__方法或__getitem__方法,将返回一个iterable .如果它实现了两者,__iter__则使用.如果它没有你得到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]
Run Code Online (Sandbox Code Playgroud)

用法:

>>> data = range(10)
>>> print [x*x for x in GetItem(data)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Run Code Online (Sandbox Code Playgroud)

这是一个实现的例子__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)
Run Code Online (Sandbox Code Playgroud)

用法:

>>> data = range(10)
>>> print [x*x for x in Iter(data)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Run Code Online (Sandbox Code Playgroud)

如您所见,您需要同时实现迭代器,并__iter__返回迭代器.

你可以结合它们:

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
Run Code Online (Sandbox Code Playgroud)

用法:

>>> well, you get it, it's all the same...
Run Code Online (Sandbox Code Playgroud)

但是那时你只能同时拥有一个迭代器.好的,在这种情况下你可以这样做:

class CheatIter(object):
    def __init__(self, data):
        self.data = data

    def __iter__(self):
        return iter(self.data)
Run Code Online (Sandbox Code Playgroud)

但这是作弊,因为你只是重复使用的__iter__方法list.更简单的方法是使用yield,并__iter__生成一个生成器:

class Generator(object):
    def __init__(self, data):
        self.data = data

    def __iter__(self):
        for x in self.data:
            yield x
Run Code Online (Sandbox Code Playgroud)

这是我推荐的方式.简单高效.


900*_*000 5

X必须是可迭代的.它必须实现__iter__()返回迭代器对象; 迭代器对象必须实现next(),每次调用时都会返回下一个项目,StopIteration如果没有下一个项目,则返回a .

列表,元组和生成器都是可迭代的.

请注意,普通for运算符使用相同的机制.

  • X可以实现`__getitem__`. (2认同)