当前位置: 代码迷 >> 综合 >> day15 生成器与迭代器以及面向过程的思想
  详细解决方案

day15 生成器与迭代器以及面向过程的思想

热度:41   发布时间:2024-01-31 02:53:41.0

迭代器

? 迭代:一次次对过程进行重复获得其中的结果,然后把该结果作为下一次运行的初始值,其中一次重复被称为一次迭代

? 例如下面的while循环,一次循环便被称为一次迭代。

goods=['mac','lenovo','acer','dell','sony']index=0
while index < len(goods):print(goods[index])index+=1

可迭代对象

? 个人理解:可以进行迭代操作的对象被称为可迭代对象

迭代器对象

? 调用obj.iter()或iter(可迭代对象)返回的结果就是迭代器对象

a=[1,2,3]
b = a.__iter__()
print(b)
>>><list_iterator object at 0x0116E520>#iterator代表的就是迭代器

? 如上图所示返回了一个列表的地址,而这个地址就是迭代器对象

? 我们可以利用next(迭代器对象)进行取值

迭代器

器:工具

迭代器:就是一种不依赖于索引的取值工具

个人理解:可以进行循环取值的容器

for循环原理

现在我们使用while循环实现取值(不用索引)

a=[1,2,3]
b = iter(a)#获得迭代对象
while True:try:c = next(b)except StopIteration:#抓取StopIteration异常break

for循环又称为迭代循环,for循环工作原理如上所示

for循环在工作时,先取得迭代对象,然后调用next方法将其赋值给in前面的变量名,执行循环,直到抓取到异常

迭代器是一种特殊的状态,当一个迭代对象被赋值给另外一个变量时,那个变量可以调用next()方法时,他就是迭代器

迭代器的缺点和优点

优点:

1.为序列和非序列提供了一种统一的迭代取值方式

2.惰性计算:迭代器可以在需要的时候再去用next()计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,因此可以存放无穷大的数据流。而对于其他容器类型,像列表,需要同时把元素放在内存中,因此可以存放的数是有限的

缺点:

1.除非取尽,否则无法获取迭代器的长度

2.只能取下一个值,不能回头

文件对象直接就是迭代器对象,其他数据类型是可迭代对象

生成器

一个函数,若是它体内包含yield关键字,那么这整个函数返回的值便被称为生成器对象。

#yield后面紧跟的值会被作为返回值返回
def test():while True:print("111")yield 1print("222")yield 2print("333")yield 3
print(test().__next__())
>>>111#print打印的
1#yield返回的值

其实生成器本身就是一个迭代器我们可以调用他本身有的方法

def test():while True:print("111")yield 1print("222")yield 2print("333")yield 3
#可以看见有__iter__方法
res=test().__iter__()
print(res)
>>><generator object test at 0x0375AAA8>#generator即为生成器

事实上,生成器是python为我们提供的自己创建迭代器的一种方法

他的运行方式是每次一碰到yield便会停下并记录位置,然后返回一个yield 后面的值,我们可以调用next方法使他继续运行

def test():while True:print("111")yield 1print("222")yield 2print("333")yield 3res=test()
print(next(res))#碰见第一个yield函数停下,返回1
print(next(res))#碰见第二个yield停下,返回2
print(next(res))#碰见第三个yield停下,返回3
print(next(res))#进行循环重新碰见第一个yield停下,返回1

yield的表达式应用

上面的便是yield的基本用法

def test():while True:print("111")food = yieldprint("%s"%food)res=test()#获得生成器对象
print(res)
next(res)#停在第一个yield处
res.send("桃子")#传值给yield,yield再传值给food
>>><generator object test at 0x0368AA70>
111
桃子
111
#运行完print后再次进行循环回到yield,若使用next(res)之前传的值并不会保存
#res.send()等于next(res),并进行了一次传值

yield也可以配合装饰器进行初始化

def init(func):def wrapper(*args, **kwrags):a = func()  # 生成器对象print(a)next(a)return a  # 如果不返回生成器对象, 那就只是运行了一次wrapper函数 倘若你要赋值给一个变量无返回值自然就不能令该变量指向生成器地址,所以必须要return!return wrapper@init  # eater = init(eater) 也就是wrapper
def eater():while True:print("你个大傻逼")food = yieldprint("我爱吃%s" % food)generator = eater()
# print(generator.send("桃子"))
print(generator)

面向过程编程

这是一种思维方式。这种思维方式是不局限于任何一种编程工具的。

定义:

面向过程的核心就是过程2个字,过程指的是解决问题的步骤,即先干什么再干什么。

面向过程设计程序就像是一条流水线。

你应该先想好让一个函数干什么,另一个函数再干什么。

优点:

? 可以使复杂的问题流程化,进而简单化

缺点:

? 可扩展性差,修改任意一个阶段,都会牵一发动全身导致程序出现问题

三元表达式、列表生成式、生成器表达式

1.三元表达式

? a = 条件达成时返回的值 if 条件 else 条件未达成时返回的值

x=30
y=20
a = x if x < y else y
print(a)
>>>20

2.列表生成式

#我们普通的通过循环将值放入列表的方式如下所示
my_list = [] 
for i in range(10):my_list.append(i)
print(my_list)
>>>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#而python为我们提供了方法把上面那种方式简化
my_list = [i for i in range(10)] #my_list = [赋值的数 for 赋值的数 in 迭代器]
print(my_list)
>>>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

3.生成器表达式

生成器的方式于列表生成器类似,只需要把[]换成()即可

with open('db.txt','rb') as f:nums=(lines for lines in f)#使用f.read()他会将一个个字符设为分割点print(nums)print(nums.__next__())print(nums.__next__())print(nums.__next__())