1.可迭代对象
1.1定义
迭代:没次更新都必须依赖上一次的结果,其目的通常是为了逼近所需目标或结果。
Python中内置__iter__方法都是可迭代对象。
一般情况下所有的双下方法都会有一个与之对应的简化写法的函数
__iter__ --> iter()
内置的方法可以通过点方法查看。
针对双下划线开头,双下滑线结尾的方法标准的读法是 双下方法名 例 双下iter。
1.2例子
1.非迭代
更新没有依赖上一次的结果.
num = 0
while True :
print ( num)
2.迭代
在上一次的基础上更新.
num = 0
while True :
print ( num)
num += 1
1.3可迭代类型
迭代器对象 又称为 迭代器
可迭代对象 又称为 迭代对象
迭代器.__iter__()方法将可迭代对象转成迭代器对象。
可迭代对象.__iter__() --生成--> 迭代器
常用数据类型中:
字符串,列表,字典,元组,集合,文件 都是可迭代对象.
'' . __iter__( )
[ ] . __iter__( )
{ } . __iter__( )
tuple ( ) . __iter__( )
set ( ) . __iter__( )
f = open ( 'a.txt' , 'wb' )
f. __iter__( )
2.迭代器
2.1定义
含有__iter__() 与 ___next__()方法的就是迭代器。
可迭代对象.__iter__() --生成--> 迭代器
文件对象即是可迭代对象,也是迭代器对象。
迭代器是一种不依赖索引取值的方式。
f. __next__( )
2.2转迭代器
可迭代对象都可以转为迭代器.
str1 = '123' . __iter__( )
list1 = [ 1 , 2 , 3 ] . __iter__( )
dic = { 'k1' : 'v1' } . __iter__( )
tuple1 = ( 1 , 2 , 3 ) . __iter__( )
set1 = { 1 , 2 , 3 } . __iter__( )
str1. __next__( )
list1. __next__( )
dic. __next__( )
tuple1. __next__( )
set1. __next__( )
2.3迭代器取值
迭代器对象执行__next__方法取值,一次取一个元素。
迭代器取完值后在执行__next__方法取值就会报错 StopIteration (停止迭代)。
str1 = 'abc' . __iter__( )
print ( str1. __next__( ) )
print ( str1. __next__( ) )
print ( str1. __next__( ) )
print ( str1. __next__( ) )
2.4案例
每次str1.__iter__()都生成一个新的迭代器对象。
所以每次.__next__() 取的值都是同一个.
str1 = 'abc'
print ( str1. __iter__( ) . __next__( ) )
print ( str1. __iter__( ) . __next__( ) )
print ( str1. __iter__( ) . __next__( ) )
print ( str1. __iter__( ) . __next__( ) )
2.5for循环
2.1原理
for循环原理:
1.后关键字in后面的数据先调用.__iter__()方法转为迭代器对象。
2.循环执行.__next__()方法取值。
3.取完之后再次执行.__next__()就会报错,但是for循环会自动捕获错误并处理。
2.2while练习
for 能做的 while都能做。
l1 = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 11 , 22 , 33 , 44 , 55 ]
list1 = l1. __iter__( )
count = len ( l1)
while count:
print ( list1. __next__( ) )
count -= 1
2.3递归练习
l1 = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 11 , 22 , 33 , 44 , 55 ]
list1 = l1. __iter__( )
count = len ( l1)
def func ( count) :
if count == 0 :
return
print ( list1. __next__( ) )
return func( count - 1 )
func( count)
3.异常捕获
3.1定义
1.异常代码运行出错会导致异常,异常发送后如果没有解决方案则直接结束程序。
2.异常三个组成部分
2.1 traceback 代码错误所在的行
2.2 xxxError 错误类型
2.3 冒号 错误的详情原因,解决bug的关键
错误类型:
1.语法错误:不能出现,语法出错就立刻修复。
2.逻辑错误:可以被出现,逻辑就尽快修复。
""" 修改逻辑错误的过程骑手就是从头到尾清理思路的过程 """
3.2语法结构
try:
被检测的代码
except 错误类型 as e:
被检测代码出错后的处理机制。 e变量名 接收错误信息。
try :
name
except NameError as e:
print ( e, '结束程序运行!' )
Exception 是所有异常的父类,所有异常都可以检测到。
3.3for循环
l1 = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 11 , 22 , 33 , 44 , 55 ]
list1 = l1. __iter__( )
while True :
try :
print ( list1. __next__( ) )
except Exception:
break
不推荐使用迭代。
执行一次就有一句try语句。
try语句检测程序会占用额外的资源。
l1 = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 11 , 22 , 33 , 44 , 55 ]
list1 = l1. __iter__( )
def func ( list1) :
try :
print ( list1. __next__( ) )
except Exception:
return
return func( list1)
func( list1)
4.取值对比
迭代取值于索引取值对比:
迭代:不依赖于索引取值,通用取值方式。
顺序永远都是往下一个取值,无法重复获取。
索引:需要提供有序的容器类型,才能取值,不通用取值方式。
可以重复取值
5.生成器
5.1定义
生成器 <==> 生成器对象
生成器就是自定义制作迭代器。
5.2定义生成器
关键字 yield
生成器 ==> 迭代器
但函数体内含有yield关键字 那么在第一调用函数的时候,并不会执行函数代码,而是将函数变成生成器。
def my_ge ( ) :
print ( '你好' )
yield
my_ge( )
5.3获取值
一个yield对应一个__next__。
以yield为分割点分, 一个yield与它之前的代码为迭代器的一个元素。
执行一次.__next__()代码往下运行到yield 就停止,放回后面yield之前的数据。
再次执行一个.__next__()代码接着上次停止的地方继续往后, 在次遇到yield再停止。
如果yield 后面还有语句,而语句后面没有yield,这个语句就不会在执行。
def my_ge ( ) :
print ( '你好1' )
yield
print ( '你好2' )
yield
print ( '你好3' )
yield
print ( '你好4' )
yield
print ( '你好5' )
res = my_ge( )
res. __next__( )
res. __next__( )
res. __next__( )
res. __next__( )
5.4实例
def my_range ( start_num, end_num= None , len_num= 1 ) :
if not end_num:
end_num = start_num
start_num = 0
while start_num < end_num:
yield start_num
start_num += len_num
for i in my_range( 1 , 10 , 2 ) :
print ( i)
6.yield关键字
6.1对比
yield
1. 可以设置返回值 yield 返回值 (支持多个值并组织成元组。)
在阻塞在yiele 语句时, 会将yield后面的值放回给迭代器对象。
2. 函数体代码遇到 yield 不会在往后运行 进入阻塞态
3. 第三种传值的方式 yeied 可以将函数变成生成器,还可以接受传值。
return
1.可以有返回值 (支持多个值并组织成元组。)
2.函数体遇到return直接结束
6.2yield传值
yield 有对应的 .send方法进行传值。
格式:
迭代器对象.send(参数1,···)
函数中:
value=yield
.send()方法
不带任何参数(None表示)==> 等同于 next 方法
在阻塞在yiele 语句时, 会将yiele 后面的值返回
带一个参数,先将值通过send传递给tield 在赋值给变量。
6.3不带参数
def my_ge ( ) :
while True :
yield 1
res = my_ge( )
print ( res. __next__( ) )
print ( res. __next__( ) )
def my_ge ( ) :
while True :
yield 1
res = my_ge( )
print ( res. send( None ) )
print ( res. send( None ) )
6.4带参数
程序中第一次使用生成器调用 send() 函数时,不能使用带参数的 send() 函数。
def my_ge ( ) :
while True :
num = yield
print ( num)
res = my_ge( )
print ( res. send( 1 ) )
"""
# TypeError: can't send non-None value to a just-started generator 报错
无法向刚启动的生成器发送非None值
"""
def my_ge ( ) :
while True :
num = yield
print ( num)
res = my_ge( )
print ( res. __next__( ) )
res. send( 1 )
res. send( 2 )
7.生成器表达式
生成器表达式内部的代码只有在迭代值的时候才会执行。
迭代器节省空间,只有在我们取值的时候迭代器才会产生值。
d1 = ( i for i in range ( 10 ) )
for i in d1:
print ( i, end= ' ' )
def test ( ) :
for i in range ( 4 ) :
yield i
g = test( )
for n in [ 1 , 10 ] :
g = ( i + n for i in g)
res = list ( g)
print ( res)