python2/3 可迭代对象(iterable),迭代器(iterator),生成器(generator),推导式(comprehension)详解

目录

 1. iterable 可迭代对象:

2. iterator迭代器:

3. generator function 生成器

4. 通过推导式实现Generator【生成器】

5. 推导式


简介:

  1. iterable 可迭代对象: 实现__iter__(self)方法的对象
  2. iterator同时实现 __iter__(self) 和 __next__(self) [python3]方法的对象, python2中实现 next(self) 方法
  3. Generator 函数 包含yield语句的函数,该函数返回一个Generator【生成器】,同时也是Iterator【迭代器】维基百科:https://wiki.python.org/moin/Generators
  4. 推导式:列表,集合,字典

关系:Generator是特殊的Iterator【迭代器】,同时他们都是可迭代对象,list,tuple,set,dict也是可迭代对象


 1. iterable 可迭代对象:

实现了 __iter__(self) 方法的对象,在该方法中返回一个迭代器或者实现了next(python2)或者 __next__(self) (python3)的对象

常见可迭代对象:tuple,list,set,dict

from collections import Iterable, Iterator

print(isinstance(dict(), Iterable))  # True
print(isinstance(dict(), Iterator))  # False
# list, set, tuple 类似

          示例:

class Test:
    def __init__(self):
        # 实现next方法的对象,该对象能通过next()方法调用获取下一个值,从而实现迭代
        self.__max = 10
        self.__cur_num = 0

    def __next__(self):  # python3 实现
        return self.next()

    def next(self):  # python2 中实现
        if self.__cur_num < self.__max:
            tmp, self.__cur_num = self.__cur_num, self.__cur_num + 1
            return tmp
        else:  # 用于终止循环
            raise StopIteration()        

class MyIterable(object):
    """iterable, 可迭代对象,实现了__iter__方法"""
    def __iter__(self):
        return Test()

from collections import Iterable, Iterator

isinstance(MyIterable(), Iterable)  # True
isinstance(MyIterable(), Iterator)  # False
isinstance(Test(), Iterable)  # False
isinstance(Test(), Iterator)  # False

2. iterator迭代器:

同时实现 __iter__() 和 __next__ 方法的对象【python2中要实现next()方法 】

class MyIterator(object):
    """iterable, 可迭代对象,实现了__iter__方法"""
    def __init__(self):
        # 实现next方法的对象,该对象能通过next()方法调用获取下一个值,从而实现迭代
        self.__max = 10
        self.__cur_num = 0

    def __iter__(self):
        # 返回对象本身,因为自身实现了 __next__ 方法
        return self

    def __next__(self):  # python3 实现
        return self.next()

    def next(self):  # python2 中实现
        if self.__cur_num < self.__max:
            tmp, self.__cur_num = self.__cur_num, self.__cur_num + 1
            return tmp
        else:  # 用于终止循环
            raise StopIteration()   

from collections import Iterable, Iterator

isinstance(MyIterable(), Iterable)  # True
isinstance(MyIterable(), Iterator)  # True

3. generator function 生成器

生成器函数:具有iterator行为,即一种特殊类型的迭代器

实现 yield关键字 语句的函数(function)为生成器函数,yield是返回值的意思,不同于return,return返回值的同时函数退出运行,而yield不会退当循环继续时他会继续执行后面语句,知道完成迭代

def my_iter(n=10):
    cur = 0
    while True:
        if cur < n:
            yield cur
            cur += 1
        else:
            break

m = my_iter()  # 返回一个迭代器同时也是生成器,my_iter为生成器函数

from collections import Iterable, Iterator
isinstance(my_iter(), Iterator)  # 返回 True

from collections import Generator  # 只有python3中有Generator对象
isinstance(my_iter(), Generator)  # 返回True

4. 通过推导式实现Generator【生成器】

# 示例, 可以先看推导式介绍,然后在看此内容
string = 'Furthermore, this is a pattern that we will use over and over for many similar constructs. Imagine writing all that just to get an iterator. '
my_iter = (i for i in string.strip().split(' ')) 

# 检测
from collections import Iterable, Iterator
isinstance(my_iter, Iterator)  # 返回 True

from collections import Generator  # 只有python3中有Generator对象
isinstance(my_iter, Generator)  # 返回True

5. 推导式

# 详解:
    数据准备:
    iterable = [1, 2, 3, 4, 5]  # 示例
1. 列表推导式
    基本格式:
        m_list = [i for i in iterable if i >= 0]
    解析:
        [变量处理[可以不做处理,可以是有返回值的函数,或者表达式] for 变量 in 可迭代对象 if 条件[过滤掉不符合条件的]]  # if 部分可以没有
        m = [i ** 2 for i in iterable if i >= o]
        def func(x):
            return x * x
        m = [func(i) for i in iterable]
        m = [(lambda x: x * x)(i) for i in iterable]  # 使用 lambda函数【匿名函数】

2. 集合推导式
    基本格式
        m = {i for i in iterable if i > 0}   # i 必须为可哈希的对象
        于列表推导式区别:
            (1) 使用大括号`{}`
            (2) i 元素必须可哈希
    其余同列表推导式

3. 字典推导式
    基本格式
        m = {k: v for k, v in iterable}  # 其中也可以加 if 条件
        m = {k: True for k in iterable}  # 其中最大括号部分k, v 可以写表达式或者函数,同列表推导式

注:
    没有元组推导式,因为小括号的为Generator【生成器】
    可以通过tuple(i for i in [1, 2, 3])该方式生成
4. 高级
    推导式用可以有多个for循环
    m = [i * j for i in iter1 for j in iter2]  # 类似于笛卡尔积结果
    笛卡尔积: https://baike.baidu.com/item/%E7%AC%9B%E5%8D%A1%E5%B0%94%E4%B9%98%E7%A7%AF/6323173?fr=aladdin
    如果i也是可迭代的,则第二个循环对i循环
    例如:
        iter1 = [[1, 2, 3], [4, 5]]
        m = [j for i in iter1 for j in i]
        

我就写到这里了,推导式中还可以嵌套实现复杂推导式,可以自己研究啊,下面放一个综合应用的例子:

# 自己实现的解析GTF文件的类【生物信息分析中使用】
# 涉及到的技术,python2和python3兼容
#     上下文管理
#     列表推导式,字典推导式, 迭代器

class GtfFile(object):
    def __init__(self, file_path):
        self.__file_handler = None
        self.__file_path = file_path

    def __init_handler(self):
        self.__file_handler = open(self.__file_path)
        seek = 0
        while True:
            line = self.__file_handler.readline()
            if not line.startswith('#') and line != '\n':
                self.__file_handler.seek(seek)
                break
            seek = self.__file_handler.tell()

    def __enter__(self):
        if self.__file_handler is None:
            self.__init_handler()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.__file_handler.close()

    def __iter__(self):
        if self.__file_handler is None:
            self.__init_handler()
        return self

    def __next__(self):
        """
        python3 iterator iter method
        :return:
        """
        if self.__file_handler is None:
            self.__init_handler()
        line = self.__file_handler.readline()
        if not line:
            raise StopIteration
        line_splits = line.strip().split('\t')
        line_splits[3] = int(line_splits[3])
        line_splits[4] = int(line_splits[4])
        line_splits[8] = {
            k.strip(): v.strip(' "')
            for k, v in (
            item.strip().split(' ', 1) for item in line_splits[8].strip('; ').split(';')
        )
        }
        return line_splits, line

    def next(self):
        """
        python2 iterator iter method
        :return:
        """
        return self.__next__()


# 使用示例

file = r'your file path'
with GtfFile(file) as gtf_handler:
    # line_list: 为解析后行内容, line: 为原行字符串[ 没做任何处理 ]
    for line_list, line in gtf_handler:
        attr_dict = line_list[8]
        gene_id = attr_dict.get('gene_id')
        pass

 

你可能感兴趣的:(python,编程)