迭代器
什么是迭代器
迭代,更新换代(重复)的过程,每次的迭代都必须基于上一次的结果
迭代器:迭代取值的工具
为什么要用迭代器
迭代器给你提供了一种不依赖于索引取值的方式
# 需要迭代取值的对象
# 列表 字典 字符串 元组 集合
n = 0 while True: print(n) 这里只是简单的重复 死循环 电脑不好的别轻易尝试啊
重复的+每次迭代都是基于上一次的结果而来的 l = [1,2,3,4] s = 'hello' n = 0 while n < len(l): print(s[n]) # h e l l 输出四个数字为什么不输出o 看判断条件 n += 1
可迭代对象
只有内部有__iter__方法的就是可迭代对象
在基本数据类型中可以迭代的对象有
字符串 列表 tuple dict set 文件类型(文件类型本身就是迭代器对象)
n = 1 f = 1.11 s = [1,2,3] d = {'name':'james','age':'22'} t = (1,2,3,4,5,6,) set1 = {1,2,3,4,56,7,7} file1 = open(r'E:程序第四周xxx.txt','w',encoding='utf-8') print(s.__iter__()) # <list_iterator object at 0x00000000027A3A20> print(d.__iter__()) # <dict_keyiterator object at 0x00000000024868B8> print(t.__iter__()) # <tuple_iterator object at 0x00000000027A3A20> print(set1.__iter__()) # <set_iterator object at 0x00000000027A93A8> print(file1.__iter__()) # <_io.TextIOWrapper name='E:\程序\第四周\xxx.txt' mode='w' encoding='utf-8'> 说明这几种数据类型可以被迭代 那么也就是说可迭代对象执行内置的__iter__方法得到的就是该对象的迭代器对象
迭代器取值
迭代器对象(句点符)
1 内置有__iter__方法
2 内置有__next__方法
PS 迭代器一定是可迭代对象
但是可迭代对象不一定是迭代器对象
迭代器取值特点:只能从前向后一次取值 不能倒着取值
总结可迭代对象/迭代器对象
可迭代对象,内置有__iter__方法
迭代器对象,内置有__iter__ 和 __next__方法的
迭代取值:
优点
1 可以不依靠索引取值
2 内存内永远只有占用一份空间,不会导致内存溢出
缺点
1 因为不能依靠索引取值,所以不能获取指定的元素
2 当取的元素多余原元素时候就会报StopIteration的错误
生成器
l = [1,2,3,4] 生成一个迭代器 iter_l = l.__iter__() # 内置有__iter__方法 所以符合条件 就是一个迭代器对象 进行对迭代器的取值 低啊用__next__ print(iter_l.__next__()) # 1 print(iter_l.__next__()) # 2 print(iter_l.__next__()) # 3 print(iter_l.__next__()) # 4 print(iter_l.__next__()) # StopIteration 报这个错误 因为值已经取完了
dic = {'name':'james','pwd':'123','hobby':'basketball'} 将这个字典dic转换成迭代器对象 iter_dic = dic.__iter__() 接下来取值 print(iter_dic.__next__()) # name print(iter_dic.__next__()) # pwd print(iter_dic.__next__()) # hobby print(iter_dic.__next__()) # StopIteration 又是这个错误 那说明字典中的key已经被我们取完了
异常处理
while True: try: print(iter_d.__next__()) except StopIteration: # print('老母猪生不动了') break 当在取值的时候如果报错信息是 StopIteration 那么pycharm就会提示你 然后结束循环取值
for循环的本质
# 用了这么久的for循环取值,一直不知道什么原理吧,那就来搂一眼
# for 循环结构
# for 变量名 in 一个可迭代对象 也就是说 for循环 后面的容器类型 必须是可迭代对象
for循环本质:
1 将in后面的容器类型调用__iter__转型成迭代器对象
2 调用__next__方法依次取值
3 内部有异常捕获 StopIteration 时候 __next__ 会自动循环结束 也就是错与元素个数时候会报StopIteration这个错
生成器 本身就是一个迭代器 只不过是我们自己定义的迭代器
那就自己定义一个
def func(): print('frist') #frist yield 666 # 666 print('second') # second yield 777 # 777 print('third') # third yield 888 # 888 print('forth') # forth yield # None # yield后面的就是在调用迭代器__next__方法 输出你可以得到的值 # yield既可以返回一个值也可以返回多个值 多个值的返回类型是元组 g = func() # 现将生成器初始化:将函数变成迭代器 print(g) # 出来个老母猪 下面开始下仔仔 print(g.__next__()) print(g.__next__()) print(g.__next__()) print(g.__next__()) # print(g.__next__()) # StopIteration
自定义一个range函数 print(range(10)) # 老母猪 range(0, 10) 看一下range是这么工作的 for i in range(10): print(i) def my_range(start, end, step=1): while start < end: yield start start += step for j in my_range(1, 100, 2): print(j)
yield(纯了解)
yield支持外界为其传参
def dog(name):
print('%s 准备开吃'%name)
while True:
food = yield
print('%s 吃了 %s'%(name,food))
def index():
pass
当函数内有yield关键字的时候,调用该函数不会执行函数体代码
而是将函数变成生成器
g = dog('egon')
g.__next__() # 必须先将代码运行至yield 才能够为其传值
g.send('狗不理包子') # 给yield左边的变量传参 触发了__next__方法
g.send('饺子')
yield
1.帮你提供了一种自定义生成器方式
2.会帮你将函数的运行状态暂停住
3.可以返回值
与return之间异同点
相同点:都可以返回值,并且都可以返回多个
不同点:
yield可以返回多次值,而return只能返回一次函数立即结束
yield还可以接受外部传入的值
生成器表达式
# 生成器表达式 res = (i for i in range(1,1000000) if i!= 4) # 生成器表达式 有木有发现这个是按照推理应该是元组生成式 不不不 没有元组生成式 print(res) # <generator object <genexpr> at 0x00000000024ADDB0> 看来是个老母猪 所以又要让老母猪下崽崽了 ''' 生成器不会主动的执任何一行代码 必须通过__next__触发代码的运行 ''' print(res.__next__()) # 1 print(res.__next__()) # 2 print(res.__next__()) # 3 print(res.__next__()) # 5
常用的内置函数
print(abs(-11.11)) # 11.11 求绝对值 l = [0,1,0] print(all(l)) # False 只要有一个为False就返回False print(any(l)) # True 只要有一个位True就返回True def index(): username = '我是局部名称空间里面的username' print(locals()) # 当前语句在哪个位置 就会返回哪个位置所存储的所有的名字 print(globals()) # 无论在哪 查看的都是全局名称空间 index() print(bin(10)) # 0b1010 print(oct(10)) # 0o12 print(hex(10)) # 0xa print(int('0b1010',2)) # 10 print(bool(1)) # True print(bool(0)) # False s = 'hello' print(s.encode('utf-8')) # b'hello' print(bytes(s,encoding='utf-8')) # b'hello' # 可调用的(可以加括号执行相应功能的) l = [1,2,3] def index(): pass print(callable(l)) # False print(callable(index)) # True print(chr(97)) # a 将数字转换成ascii码表对应的字符 print(ord('a')) # 97 将字符按照ascii表转成对应的数字 dir获取当前对象名称空间里面的名字 l = [1,2,3] print(dir(l)) import test print(dir(test)) print(test.name) divmod 分页器 print(divmod(101,10)) total_num,more = divmod(900,11) if more: total_num += 1 print('总页数:',total_num) enumerate 枚举 l = ['a','b'] for i,j in enumerate(l,1): print(i,j) eval exec s = """ print('hello baby~') x = 1 y = 2 print(x + y) """ eval(s) exec(s) eval不支持逻辑代码,只支持一些简单的python代码 s1 = """ print(1 + 2) for i in range(10): print(i) """ eval(s1) exec(s1) name = 'jason' s2 = """ name """ print(eval(s2)) format 三种玩法 {}占位 {index} 索引 {name} 指名道姓 print(globals()) def login(): """ 一起嗨皮 :return: """ print(help(login)) isinstance 后面统一改方法判断对象是否属于某个数据类型 n = 1 print(type(n)) print(isinstance(n,list)) # 判断对象是否属于某个数据类型 print(pow(2,3)) # 8 2的3次方 print(round(3.4)) # 四舍五入 """ 面向对象需要学习的方法 classmethod delattr getattr hasattr issubclass property repr setattr super staticmethod """