TOPIC

磷光与烟火逆流

一个敲代码的程序猿

Python之迭代器与生成器

迭代器

  1. 可迭代对象

    字面意思分析:可以重复的迭代的实实在在的东西。

    list,dict(keys(),values(),items()),tuple,str,set,range, 文件句柄(待定)

    专业角度: 内部含有'__iter__'方法的对象,就是可迭代对象。

    内置函数:dir()
    print(dir(str))

    判断一个对象是否是可迭代对象:
    print('iter' in dir(str))

    优点:

    1. 直观。
    2. 操作方法较多。

    缺点:

    1. 占内存。
    2. 不能迭代取值(索引,字典的key)。
  2. 迭代器

    字面意思:可以重复迭代的工具。

    专业角度: 内部含有'__iter__'并且含有"__next__"方法的对象,就是迭代器

    可迭代对象转化成迭代器:

    l1 = [1, 2, 3, 4, 5]
    # 内置函数iter()
    obj = iter(l1)
    
    # 迭代器可以迭代取值。利用next()进行取值
    l1 = [1, 2, 3, 4, 5]
    # 内置函数iter()
    obj = iter(l1)
    # print(obj)
    print(next(obj))
    print(next(obj))
    print(next(obj))
    print(next(obj))
    print(next(obj))
    print(next(obj))
    
    

    迭代器优点:

    1. 非常节省内存。
    2. 惰性机制。

    迭代器缺点:

    1. 不直观。
    2. 操作不灵活。
    3. 效率相对低。

    特性:

    l1 = [22, 33, 44, 55, 66, 77]
    obj = iter(l1)
    
    for i in range(3):
        print(next(obj))
    
    for i in range(2):
        print(next(obj))
    

    利用while循环,模拟for循环内部循环可迭代对象的机制。

    1. 先要将可迭代对象转化成迭代器。
    2. 利用next对迭代器进行取值。
    3. 利用异常处理try一下防止报错。
  3. 可迭代对象与迭代器的对比

    可迭代对象:

    ​ 是一个私有的方法比较多,操作灵活(比如列表,字典的增删改查,字符串的常用操作方法等),比较直观,但是占用内存,而且不能直接通过循环迭代取值的这么一个数据集。

    应用:当你侧重于对于数据可以灵活处理,并且内存空间足够,将数据集设置为可迭代对象是明确的选择。

    迭代器:

    ​ 是一个非常节省内存,可以记录取值位置,可以直接通过循环+next方法取值,但是不直观,操作方法比较单一的数据集。

    应用:当你的数据量过大,大到足以撑爆你的内存或者你以节省内存为首选因素时,将数据集设置为迭代器是一个不错的选择。(可参考为什么python把文件句柄设置成迭代器)。

生成器

生成器初始

  • 生成器本质就是迭代器。python社区生成器与迭代器是一种。生成器与迭代器的唯一区别:生成器是我们自己用python代码构建的。

生成器产生方式

  • 生成器函数。
  • 生成器表达式。
  • python给你提供的一些内置函数,返回一个生成器。

生成器函数。

  • 之前接触的函数:

    # def func():
    #     print(111)
    #     return 2
    # ret = func()
    # print(ret)
    # 执行此函数,遇到return结束函数。
    # 将数字2返回给ret。
    
    
  • 生成器函数: 只要函数中出现了yield那么他就不是函数,它是生成器函数

    def func():
        # print(111)
        # print(111)
        # print(111)
        # print(111)
        # print(111)
        # print(111)
        yield 2,4,5
        yield 3
        yield 4
        yield 5
    ret = func()  # 生成器对象
    # print(ret)  # <generator object func at 0x0000000001E10F68>
    '''
    # 类比
    l1 = [2,]  [2,3,4,5]
    obj = iter(l1)
    
    '''
    # 只要函数中出现了yield那么他就不是函数,它是生成器函数。
    # 一个next对应一个yield.
    # print(next(ret))
    # print(next(ret))
    # print(next(ret))
    # print(next(ret))
    # print(next(ret))
    # print(next(ret))
    
    

yiled与return的区别

# return 结束函数,给函数的执行者返回值(多个值通过元组的形式返回)。
# yield  不结束函数,对应着给next返回值(多个值通过元组的形式返回)。

send(了解)

pass

生成器的举例

# def eat_baozi():
#     list1 = []
#     for i in range(1,2001):
#         list1.append(f'{i}号包子')
#     return list1
#
# print(eat_baozi())

def eat_baozi_gen():
    for i in range(1,2001):
        # print(11)
        yield f'{i}号包子'

'''
# ret1 = eat_baozi_gen()
# ret2 = eat_baozi_gen()
# # print(ret1)
# # print(ret2)
# print(next(ret1))
# print(next(ret1))
# print(next(ret1))
# 
# print(next(ret2))
# print(next(ret2))
# print(next(ret2))
# print(next(ret))
# print(next(ret))
'''

# ret = eat_baozi_gen()
#
# for i in range(200):
#     print(next(ret))
#
# for i in range(200):
#     print(next(ret))

yiled与yiled from。

# yield from


# def func():
#     l1 = [1, 2, 3]
#     yield l1
# ret = func()
# print(next(ret))
# print(next(ret))
# print(next(ret))

# def func():
#     l1 = [1, 2, 3]
#     yield from l1
#
#     '''
#     yield 1
#     yield 2
#     yield 3
#     '''
# ret = func()
# print(next(ret))
# print(next(ret))
# print(next(ret))

# yield : 对应next给next返回值
# yield from 将一个可迭代对象的每一个元素返回给next
# yield from 节省代码,提升效率(代替了for循环)

列表推导式,生成器表达式(字典推导式,集合推导式)。

  • 列表推导式:一行代码构建一个有规律比较复杂的列表。
  • 列表推导式与之前写法对比
# l1 = [1,2,3......100]
# l1 = []
# for i in range(1,101):
#     l1.append(i)
# print(l1)

# 列表推导式
l1 = [i for i in range(1, 101)]
# print(l1)

  • 两种构建方式:
    1.循环模式: [变量(加工后的变量) for 变量 in iterable]
    2.筛选模式: [变量(加工后的变量) for 变量 in iterable if 条件]

  • 循环模式:

    # 循环模式:
    # 将10以内所有整数的平方写入列表。
    # print([i**2 for i in range(1, 11)])
    # 100以内所有的偶数写入列表.
    # print([i for i in range(2, 101, 2)])
    # 从python1期到python100期写入列表list
    # print([f'python{i}期' for i in range(1, 101)])
    
    
  • 筛选模式:

    # print([i for i in range(1, 101) if i > 49])
    # 三十以内可以被三整除的数。
    # print([i for i in range(1, 31) if i % 3 == 0])
    # 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
    # l1 = ['barry', 'fdsaf', 'alex', 'sb', 'ab']
    # print([i.upper() for i in l1 if len(i) > 3])
    # 找到嵌套列表中名字含有两个‘e’的所有名字(有难度)
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    # l1 = []
    # for i in names:
    #     for j in i:
    #         if j.count('e') > 1:
    #             l1.append(j)
    # print(l1)
    
    print([j for i in names for j in i if j.count('e') > 1])
    
  • 列表推导式的优缺点:

    # 列表推导式的优缺点:
    # 优点:
        # 1, 简单,快捷,装b。
    # 缺点:
        # 2. 可读性不高,不好排错。
    # 慎用,不要入迷。
    
  • 生成器表达式:

    与列表推导式几乎一模一样。

    循环模式,筛选模式。

# obj = (i for i in range(1, 11))

# # print(obj)

# # print(next(obj))

# # print(next(obj))

# # print(next(obj))

# # print(next(obj))

# # print(next(obj))

# # print(next(obj))

# # print(next(obj))

# # print(next(obj))

# # print(next(obj))

# # print(next(obj))

# # print(next(obj))
  • 如何触发生成器(迭代器)取值?
1. next(obj)

2. for 循环

for i in obj:

    print(i)

3. 数据转化

print(list(obj))

生成器表达式:生成器 节省内存。
  • 字典推导式,集合推导式
字典推导式,集合推导式:  两种模式: 循环模式,筛选模式
l1 = ['小潘', '怼怼哥','西门大官人', '小泽ml亚']
{0: '小潘', 1: '怼怼哥', 2: '西门大官人'}
dic = {}
for index in range(len(l1)):
    dic[index] = l1[index]
print(dic)
print({i:l1[i] for i in range(len(l1))})


1~100
print({i for i in range(1, 101)})
posted @ 2018-07-08 17:33  Jacobyang  阅读(158)  评论(0编辑  收藏  举报