上海day13 -- 迭代器,生成器以及常用内置方法
2019-07-15 17:32 在上海的日子里 阅读(228) 评论(0) 编辑 收藏 举报目 录
一、迭代器
二、for 循环原理
三、生成器
四、常用内置方法
一、迭代器
解释:迭代就是在前一次的结果上重复取值,器就是工具。迭代器就是迭代取值的工具。
1、为什么要用迭代器?
迭代器不需要依赖索引取值。
2、可迭代对象:
内置只有__iter__方法的叫做可迭代对象。
3、迭代器对象:
内置不仅有__iter__方法,还有__next__方法的叫做迭代器对象。
注意:可迭代对象通过__iter__方法得到迭代器对象,迭代器对象通过__next__方法取值。
4、基本数据类型有哪些可迭代对象?
可迭代对象即内置有__iter__方法的数据类型,
1 # n = 1 2 # f = 1.1 3 s = 'hello' 4 l = [1,2,34,] 5 t = (1,2,34) 6 s1 = {1,2,3,4} 7 d = {'name':'jason'} 8 f1 = open('xxx.txt','w',encoding='utf-8')
以上实验可知:str, list, dict, tuple, set, f 都内置有__iter__方法,
特别是文件对象f 不仅有 __iter__方法还有__next__方法,说明文件对象不仅是可迭代对象还是迭代器对象。
补充小知识:
针对双下划线开头双下划线结尾的方法,python推荐读法:双下+方法名。
Python解释器为我们定制了快捷方法来代替双下划线__:
__iter__ 等价于 iter()
__len__ 等价于 len()
__next__ 等价于 next()
5、迭代器取值
迭代器取值特点:
a、前面提到过迭代器取值只能通过__next__方法。每执行一次就提取一行内容,若容器中没有可取值会报错:StopIteration
b、只能往后一次取,不能后退。
注意:文件对象及是可迭代对象又是迭代器对象
f1 = open('xxx.txt','r',encoding='utf-8') # 调用f1内置的__iter__方法 # iter_f = f1.__iter__() # print(iter_f is f1)
由以上代码可知:文件对象f 调用 __iter__方法得到是自己本身。
提出问题:为什么文件对象是迭代器对象还会有__iter__方法?
解决问题--引出:for循环原理 -- for 循环后面的in 若接的是迭代器对象,但迭代器对象没有__iter__方法的话会for循环会报错!
得出结论如下:
迭代器对象无论执行哪个多少次__iter__方法都是得到迭代器对象自己本身。(******)
6、总结:
可迭代对象内置只有__iter__方法;
迭代器对象既有__iter__方法,也有__next__方法;
迭代器对象一定是可迭代对象,但可迭代对象不一定是迭代器对象。
二、for 循环内部原理
d = {'name':'jason','password':'123','hobby':'泡m'} for i in d: print(i) # for循环后面的in关键 跟的是一个可迭代对象
for 循环内部的本质:
1、将 in 后面的对象通过 调用__iter__方法转成迭代器对象;
2、调用__next__方法迭代取值;
3、一直迭代取值,直到容器为空,报错。然后捕获异常StopIteration,当 __next__方法报错,自动结束循环。
注意:由上可知,for循环后 in对应的对象是可迭代对象。
迭代取值的优缺点:
优点:1、不依赖索引取值;
2、内存中永远只出现一行内容,不会导致内存溢出的情况出现。
缺点:1、不能指定取值;
2、当取值为空时,会报出StopIteration 的错误。
三、生成器
1、生成器:
就是用户自定义的迭代器。本质就是迭代器。
def func(): print('first') yield 666 # 函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行 print('second') yield 777 print('third') yield 888 print('forth') yield yield # yield后面跟的值就是调用迭代器__next__方法你能得到的值 # yield既可以返回一个值也可以返回多个值 并且多个值也是按照元组的形式返回 g = func() # 生成器初始化:将函数变成迭代器
2、自定义迭代器完成range()方法
def my_range(start,end,step=1): while start < end: yield start start += step for j in my_range(1,100,2): print(j)
3、生成器表达式 -- 就是元组括号:例如:res = (i for i in range(5)) 得到生成器对象。
res3 = range(10) print(res3) # range(0, 10) res2 = [i for i in range(10)] print(res2) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] res = (i for i in range(10)) print(res) # <generator object <genexpr> at 0x01A2D0F0> 得到一个生成器对象 print(res.__next__()) # 0 print(res.__next__()) # 1 """ 由上可知: 生成器不会主动执行任何一行代码 必须通过__next__触发代码的运行 """
4、yeild 关键字的特点、与return的区别等
特点:1、返回值与return一样可以返回一个值,也可以返回多个值,多个值以元组形式返回;
2、暂存函数的运行状态,
3、可以通过外接传参 (前提是代码运行到yeild的位置,才可以通过send方法传参)
args = yeild 111
send方法通过外界传参之后会自动运行下一句代码。
区别:yeild 可以执行多次,return执行一次之后函数就会结束。
5、重点!!!面试题~
解题思路:
四、常用的内置函数
abs() 求绝对值
# abs 求绝对值 print(abs(-1.11)) # 1.11
all() any() 返回布尔值
# all() any() 返回布尔值 li = [0,2,34,5] print(all(li)) # False 容器里面的元素全为True才返回True print(any(li)) # True 容器里面只要有一个元素为True 就返回True
globals() locals()
def func(): user_name = '我是局部名称空间' print(locals()) # 返回当前位置所存储的名称空间的名字 {'user_name': '我是局部名称空间'} print(globals()) # 无论在什么位置,返回的都是全局名称空间的名字 func()
bin() oct() hex() 十进制转其他进制, int('其他进制字符',进制数) 其他进制转十进制
bytes() 字符编码转换的两种形式
# bytes() 字符编码转换两种方式 x = '上海' print(x.encode('utf-8')) print(bytes(x,encoding='utf-8'))
callable()
# callable() 是否可调用... list2 = [1,2,3,4] def index(): pass print(callable(list2)) # False print(callable(index)) # True
chr() ord() ASCII码表对应字符与数字的转换
# chr() ord() ASCII码表对应字符与数字的转换 print(chr(97)) # a 将ascii码表对应数字转为字符 print(ord('a')) # 97 将ASCII码表对应字符转为数字
dir() 获取当前名称空间里的名字 / 主要用于模块中名称空间名字的查找
# dir() 获取当前名称空间里的名字 /主要用于模块中名字变量的查找 list3 = [23,34,45,66] print(dir(list3)) # 好多。。。
divmod() 分页器
# divmod() 分页器 print(divmod(121,10)) # (12, 1) 返回整除数和余数 # 网站分页的实现: num1, num2 = divmod(121,10) if num2: num1 += 1 print('当前需要的页数为:%s'%num1) # 当前需要的页数为:13
enumerate() 枚举
# enumerate() 枚举 list3 = ['jason','tank','egon'] for i ,j in enumerate(list3): print(i,j,end=' ') # 0 jason 1 tank 2 egon 默认索引从0开始 for i ,j in enumerate(list3,1): print(i,j,end=' ') # 1 jason 2 tank 3 egon 设置索引从1开始
eval() exec() 可以执行字符串内的代码
# eval() exec() str1 = """ print('hello world') # 注意:要顶格对齐!!! x = 1 y = 2 print(x+y) """ #eval(str1) # 报错! eval()只能运行简单的代码,不能进行逻辑运算 exec(str1) # hello world 3
# eval()需要注意的示例 name = 'jason' s2 = """ name """ print(eval(s2)) # jason
format() 格式化输出,三种玩法
和%s一样{}占位,{index}索引,{name}指名道姓即关键字传参
isinstance() 判断对象是否属于某种数据类型 / 推荐使该方法
# isinstance() n = 'adads' print(isinstance(n,str)) # True print(isinstance(n,dict)) # False
pow() 幂次方相乘
# pow() print(pow(3,2)) # 9 3的平方
round() 四舍五入进位整数
# round() print(round(3.49)) # 3 print(round(3.51)) # 4