迭代器和生成器

推导式

        推导式comprehensions(又称解析式),是Python的一种独有特性。推导式是可以从一 个数据序列构建另一个新的数据序列的结构体。 共有三种推导,在Python2和3中都有支持

列表推导式

基本格式:variable = [out_exp_res for out_exp in input_list if out_exp == 2]

# result = [i*1 for i in range(20) if i %3]
# print(result)
# import math
# #使用列表推导式输出100以内,开平方是整数的数
# result = [i for i in range(100) if (math.sqrt(i)%1) == 0]
# print(result)
# #对列表中的数取两位小数
# list1=[2.45345,4.3455325,82.234324,9.841234]
# result1 = [round(i,2) for i in list1]
# print(result1)
​
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva', 'Elven']]
for i in names:
    for j in i:
        if j.lower().count('e') >= 2:
            print(j)
​
result = [j for i in names for j in i if j.lower().count('e') >= 2]
print(result)

集合推导式

str1 = "fjklfjlkefjl jfso"
print(set(str1))
print({ i for i in str1})

字典推导式

基本格式:variable = {out_key:out_value for out_key,out_value in input_list if out_exp == 2}

#字典推导式
# print({x:y for x,y in [('a',1),('b',2)]})
#统计字符串中每一个字符出现的次数
# str1 = "dsfjhdsfjksdhfhdsfhkds"
# dict1 = {}
# for i in set(str1):
#     dict1[i] = str1.count(i)
# print(dict1)
# print({i:str1.count(i) for i in set(str1)})
​
#过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
# q1 = ['a','ab','abc','abcd','abcde']
# for i in q1:
#     if len(i) >3:
#         print(i.upper())
#
# print([i.upper() for i in q1 if len(i) > 3])
#求(x,y)中x是0-5之间的偶数,y是0-5之间的奇数组成的元组列表
# print([(x,y) for x in range(6) for y in range(6) if x%2 == 0 and y % 2])
# 快速更换key和value
# q3 = {'a':10,'b':34}
# print({y1:x1 for x1,y1 in q3.items()})
#合并大小写对应的value值,将k统一成小写
# q4 = {'B':3,'a':1,'b':6,'c':3,'A':4}
# print({x2.lower():q4.get(x2.lower(),0)+q4.get(x2.upper(),0) for x2 in q4})

总结

  1. 列表推导式只能构建比较负责并且有规律的列表

  2. 超过三层循环才能构建成功的,就不建议用列表推导式

  3. 查找错误(debug模式)不行

python可迭代对象

容器

        容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中。

        通常这类数据结构把所有的元素存储在内存中(也有一些特例,并不是所有的元素都放在内存,比如 迭代器和生成器对象)

可迭代对象

        凡是可以返回一个迭代器的对象都可称之为可迭代对象

可迭代对象有哪些

  • 容器都是可迭代对象

  • 此外还有更多的对象同样也是可迭代对象,比如处于打开状态的files,sockets等等。

  • 凡是可以返回一个迭代器(iter)的对象都可称之为可迭代对象

  • str,list,文件,range

如何确认一个对象是不是可迭代对象

iter方法

可迭代对象实现了iter方法,该方法返回一个迭代器对象

b = [1,2,3]
dir(b)
输出包含:[……,'__iter__',……]

使用Iterable判断

迭代器

实现了__iter__()和__next__()的都是迭代器

#__iter__方法 返回自身 #__next__方法 返回下一个值

  • 迭代器一定是一个可迭代对象

  • for循环 -- 先调用对象的__iter__方法得到一个迭代器

  • 在调用__next__方法,不断返回下一个值

  • 容器中没有更多的元素了,则抛出StopIteration

  • for循环中遇到异常就退出

  • 懒加载,惰性求值,用的时候才生成

# print(dir([1,2,3]))
# print(hasattr([1,2,3],'__next__'))
​
lst = [1,2,3]
lst_it = lst.__iter__()
lst_it2 = iter(lst)
print(hasattr(lst_it2,'__next__'))
print(lst_it.__next__())
print(next(lst_it))
#取完会抛出StopIteration的异常
​
#编写迭代器,实现range
class MyRange():
    def __init__(self,num):
        self.num = num
        self.tmp = -1
    def __iter__(self):
        return self
    def __next__(self):
        if self.tmp < self.num-1:
            self.tmp+=1
            return self.tmp
        else:
            raise StopIteration q
生成器
  • 特殊的迭代器

  • 就是为了写迭代器更加简单,优雅

  • 不需要手动实现__iter____next__方法

生成器表达式

#1.生成器表达式
lst = [4,5,6]
g1 = (x*2 for x in lst)
print(dir(g1))
print(next(g1))

生成器函数

yield关键字

保留中间算法,下次继续执行

#当调用next时,遇到yield就暂停运行,并且放回yield后面表达式的值
#当再次调用yield时,就会从刚才暂停的地方继续运行,直到遇到下一个yield或者整个生成器结束
#2.生成器函数
#yield关键字
def get_content():
    print("start yield.")
    yield 3
    print("second yield.")
    yield 4
    print("end.....")
​
g1 = get_content()
print(dir(g1))
print(next(g1))
print(next(g1))
​
def Myrange(num):
    i = 0
    while i< num:
        yield i
        i +=1
​
for i in Myrange(15):
    print(i)

生成器的好处

  • 可以用更少地中间变量写流式代码

  • 相比其它容器对象它更能节省内存

  • 可以用更少的代码来实现相似的功能

列表推导式 与生成器表达式的区别

写法上:【】()

iterable iterator

三种关系小结

  • 对象是可迭代对象, 但却不一定是迭代器

  • 如果对象属于迭代器, 那么这个对象一定是可迭代的

  • 迭代器实现了一个__next__()方法,可以通过next函数每次取出迭代器中的每个元素 •

  • 迭代器对象:__iter__()返回的是迭代器对象自身。

  • 生成器是一种特殊的迭代器

send 数据

除了可以使用 next() 方法来获取下一个生成的值,用户还可以使用 send() 方法将一个 新的或者是被修改的值返回给生成器。除此之外,还可以使用 close() 方法来随时退出 生成器

必须要激活之后的生成器才能用send,也就是说要先执行了一次next之后才能用send修改数据

def counter():
    count = 1
    while 1:
        val = yield count
        print(f'val is {val}')
        if val is not None:
            print(f'val is {val}')
            count = val
        else:
            count += 1
count = counter()
# count.sent(10)    #修改数据,必须先激活生成器,可以使用next激活
print(next(count))
print('*'*20)
print(count.send(10))    #返回一个新的值给yield count
print('*'*20)
print(next(count))

手动关闭当前生成器,关闭之后就不能再生成值了

count.close()    #手动关闭当前生成器,关闭之后就不能再生成值了,否则会报错  
print(next(count))

yield 与 yield from

def f1():
    yield range(10)
def f2():
    yield from range(4)    #后面一定要接一个可迭代对象
​
iter1 = f1()
iter2 = f2()
print((iter1))
print((iter2))
print(next(iter1))
print(next(iter2))

特大文件处理

生成器 + 切割多个小文件并行处理

怎么确保文件传完了,可以使用哈希算法(md5sum)

哈希算法

单向加密 明文--》密文 1.验证文件完整性 2.验证登录,加密传输

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值