迭代器与生成器

迭代器与生成器

一、python推导式

1.列表推导式
a = [1,2,3,4,5,6,7]
b = [x**2 for x in a if x%2 == 1]
print(b)

结果:
	[1, 9, 25, 49]

练习:
1.1 使用列表推导式,输出200以内开平方是整数的数

#方法一:
result = [i*i for i in range(15) if i*i<200]
print(result)
#方法二:
import math
tmp = [i for i in range(200) if math.sqrt(i).is_integer()]
#tmp = [i for i in range(200) if math.sqrt(i)%1==0]
print(tmp)

1.2 对列表中的数,取两位小数

tmp = [2.45345,4.3454325,9,82.234324,9.841234]
num = [round(i,2) for i in tmp ]
# num = ['%.2f'%i for i in tmp ]
print(num)
2.嵌套推导式
#统计出名字里面包含e次数大于两次的,
#方法一:常规方法
result = []
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:
          result.append(j)
print(result)

#方法二:嵌套推导式实现
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva', 'Elven']]
print([name for lst in names for name in lst if name.lower().count('e')>=2])
3.字典推导式
d1 = {"a":1,"b":2,}
d2 = {v:k for k,v in d1.items()}
print(d2)

结果:
	{1: 'a', 2: 'b'}

练习
3.1 统计字符串中每一字符出现的次数

#方法一:
str1 = "fasfasgwreasdg3tagjdhg"
print({x:str1.count(x) for x in str1 })
#方法二:
tmp = {}
for i in str1:
    tmp[i] = tmp.get( i, 0) +1
4.集合推导式

和列表推导式一致,只是这里使用{},自带去重功能

lst = [-1,1,2,1]
s1 = {i*i for i in lst}
print(s1)

结果:
	{1, 4}
5.推导式综合练习

在这里插入图片描述
答案

1、q1 = ['a','ab','abc','abcd','abcde']
print([x.upper() for x in q1 if len(x)>=3])

2print([(x,y) for x in range(6) for y in range(6) if x%2==0 and y%2!=0])

3、dict1 = {'a': 10, 'b': 34}
print({x:y for y,x in dict1.items()})

4、q4 = {'B':3,'a':1,'b':6,'c':3,'A':4}
print({x.lower():q4.get(x.lower(),0)+q4.get(x.upper(),0) for x,y in q4.items() })

python中可迭代对像和迭代器

1.可迭代对象:

实现了__iter__方法,并且该方法返回一个迭代器的对象

lst = ["x","y",1,2,3]
print(dir(lst))

from collections.abc import Iterable
print(isinstance(lst,Iterable))
print(isinstance(lst,list))
print(isinstance(lst,str))
2.目前接触的可迭代对象–容器类型
str、list、tuple、dict、set,打开的文件files、range等等
3.迭代器,实现了__iter__()和__next__()方法的都叫做迭代器
__iter__方法返回自身
__next__方法不断返回下一个值

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

str1 = "abc"
result = str1.__iter__()
print(result)
print(dir(result))
print(result.__next__())
print(result.__next__())
print(result.__next__())

range_iter = iter(range(10))
from collections.abc import Iterable,Iterator
print(isinstance(range_iter,Iterable))
print(isinstance(range_iter,Iterator))
4.for 语法糖
for 先调用可迭代对象的__iter__方法,返回一个迭代器,然后再对迭代器调用__next__方法,不断的返回下一个值,直到最后一个退出,
容器中没有更多的元素了,则抛出StopIteration,for循环遇到异常就退出
5.懒加载

惰性求值,需要的时候再生成
迭代器的作用:不会一次性消耗大量的内存,一个一个加载

lst = [1,2,3,4,5,6,7,8]  #一次性全部生成,保存在内存中
#range19
for i in range(1,9):
	print(i)
6.生成无限序列
from itertools import count
counter = count(start=10)
print(counter,type(counter))
print(next(counter))
print(next(counter))
print(next(counter))

结果:
    count(10) <class 'itertools.count'>
    10
    11
    12
7.从有限的序列中生成无限序列

在这里插入图片描述

8.实现一个迭代器
class NumIter():
    def __init__(self):
        self.num = 0
    def __iter__(self):
        return self
    def __next__(self):
        self.num +=1
        return self.num
n1 = NumIter()
print(dir(n1))

for i in n1:
    if i ==10:
        break
    print(i)
9.编写迭代器实现range
class MyRange():
    def __init__(self, num):
        self.num = num
        self.i = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.i < self.num:
            flag = self.i
            self.i += 1
            return flag
        else:
            raise StopIteration
ran  = MyRange(10)
for i in ran:
    print(i)
10、编写迭代器实现斐波拉契数列
class Fib():
    def __init__(self, num):
    #num 表示计算前n项 用以判断迭代的条件
        self.num = num
    #i 用来记录访问的位置
        self.i = 0
        self.num1 = 0
        self.num2 = 1
    def __iter__(self):
    # 可迭代对象需要提供__iter__一个迭代器,在python中, 迭代器 本身就是一个可迭代对象,返回自己
        return self
    def __next__(self):
        if self.i < self.num:
            self.num1,self.num2 = self.num2,self.num1+self.num2
            self.i += 1
            return self.num1
        else:
            raise StopIteration
fib  = Fib(10)
for i in fib:
    print(i)

三、生成器

1.生成器:不需要手动去实现__iter__和__next__方法,是迭代器更优雅的写法
2.生成器只有两个写法:

一种叫做生成器表达式,一种叫做生成器函数

3.生成器表达式

惰性求值,类似与列表推导式

result = (x for x in range(1,31) if x%3 ==0) #=====》惰性求值
print(result)
print(dir(result))

结果:
<generator object <genexpr> at 0x000002B1F715AC80>
['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
4.生成器函数:

包含了yield关键字的函数就叫做生成器函数
1、yield关键字

yield保留中间算法,下次继续执行
当调用next时,遇到yield就暂停运行,并且返回yield后面表达式的值
当再次调用yield时,就会从刚才暂停的地方继续运行,直到遇到下一个yield或者整个生成器结束为止
def get_content():
    x = 2
    yield x
    y = 3
    yield y
    z = 4
    yield z
g = get_content()
print(g)
print(dir(g))
print(next(g)) #第一次执行next的时候,遇到yield就退出,并且返回yield后面携带的参数,还会记录当前执行的位置
print(next(g)) #第二次执行的时候,就会从上一次执行的地方继续执行 
print(next(g))

结果:
<generator object get_content at 0x000001D2D9C9AAC0>
['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
2
3
4
#生成器实现range方法
def Myrange(num):
    i = 0
    while i<num:
        yield i
        i +=1
for i in Myrange(10):
    print(i)
5.生成器函数,实现斐波拉契数列
def Fib(num):
    i = 0
    num1 = 0
    num2 = 1
    while i<num:
        num1,num2 = num2,num1+num2
        yield num1
        i +=1
for i in Fib(10):
    print(i)
6.生成器的好处:
​	可以使用更少的代码来实现迭代器的效果
​	相比于容器类型更加节省内存
7.生成器对大文件的处理,可以兼顾效率和内存爆了的处理
def read_file(path):
    SIZE = 65535
    with open(path,"rb") as f:
        while True:
            block = f.read(SIZE)
            if block:
                yield block
            else:
                return 
7.1、特大大的文件处理:
生成器 + 切割多个小文件并行处理
7.2、大文件的传输
切割小文件 + 哈希验证
8.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.send(10)     #修改数据,必须先激活生成器,可以调用next激活
print(next(count))
count.send(10)      #返回一个新的值给yield count
print(next(count))

#手动关闭当前生成器,关闭之后不能再继续生成值
# count.close()
# print(next(count))
9.yield和yield from
def f1():
    yield range(10)
def f2():
    yield from range(10)
iter1 = f1()
iter2 = f2()
print(iter1)
print(iter2)
print(next(iter1))
#print(next(iter1))     #会报错,因为已经停止了
print(next(iter2))
print(next(iter2))      #yield from 后面需要传入一个可迭代对象

四、生成器、迭代器、可迭代对象三者的关系

在这里插入图片描述

五、hash算法

1、哈希算法定义
结果都是以空间换时间的的概念
把任意长度的输入,变成固定长度的输出
2、常见的哈希算法:
 md5 sha1	sha2	sha256	sha512---》单向加密技术
3、应用:
校验文件的完整性--》文件的传输;
密码验证和密码加密
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值