15 迭代器、生成器、模块和包
第16节 迭代器、生成器作业解答一, 推导表达式1,列表推导2,集合和字典推导二,生成器1,创建生成器的两种方法2, yield运行规则三,迭代器1,区分可迭代对象和迭代器2,迭代3,for实现原理4,从可迭代对象生成一个迭代器5,自定义迭代器四,模块1,模块的导入2,导入语法 与 导入路径导包导入全部包 *
作业解答
import os if not os.path.exists('my_tesr.txt'): # 判断文件是否存在 file = open('my_test.txt', 'w+', encoding='utf-8') try: my_dict = {'name': 'xiaojiu'} file.write(my_dict['name']) except Exception as e: print(e) finally: file.close() print('文件正常关闭') # 文件存在则不会运行try
一, 推导表达式
1,列表推导
-
循环添加:
>>> li = [] >>> for i in range(10): ... li.append(i) ... >>> li [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-
列表推导:
li = [i for i in range (10)]
-
列表推导+条件判断:
li2 = [i for i in range(10) if i % 2 == 0]
-
列表推导+三目运算:
li3 = [i if i % 2 == 0 else 0 for i in range(10)]
2,集合和字典推导
-
集合推导:
se = {i for i in range(10)}
-
字典推导:
li = [1,2,3,4,5,6,7,8,9,10] di = {i:j for i, j in enumerate(li)}
二,生成器
1,创建生成器的两种方法
-
列表推导式的[]改成()
>>> tu = (i for i in range(1,11)) >>> next(tu) 1 >>> next(tu) 2 >>> next(tu) 3
-
在函数里面加上 yield
>>> def func(num): a = 0 while a < num: yield a a += 1 >>> b = func(10) >>> next(b) 0 >>> next(b) 1 >>> next(b) 2
2, yield运行规则
-
yield 一个对象:返回这个对象、暂停这个对象、等待下次next重新激活
-
注意:
yield表达式只能在函数中使用,在函数体中使用yield 表达式可以使函数成为一个生成器
yield 可以返回表达式结果,并且暂定函数执行,直到next激活下一个yield
Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果,从而节省大量的空间,这也是生成器的主要好处
三,迭代器
1,区分可迭代对象和迭代器
-
可迭代对象: Iterable
可迭代对象能用for循环进行遍历
可以使用 isinstance() 判断一个对象是否是 Iterable 对象
>>> from collections import Iterable,Iterator >>> li = [1,2,3,4,5] >>> isinstance(li,Iterable) True >>> di = {'a':1,'b':2} >>> isinstance(di,Iterable) True
-
迭代器: Iterator
迭代器不仅可以通过for进一行遍历,可以通过next取值
可以使用 isinstance() 判断个对象是否是 Iterator对象
>>> from collections import Iterable,Iterator >>> li = [1,2,3,4,5] >>> li1 = iter(li) >>> isinstance(li1,Iterator) True >>> tu = (1,2,3,4,5) >>> isinstance(tu,Iterator) False
2,迭代
for 迭代变量 in 可迭代对象,每一次循环都会自动让“迭代变量”指向“下一个元素” 。
# 例1 li = [1,2,3,4,5] for i in li: print(i) # 例2 li = [1,2,3,4,5] index = 0 var = None while index < len(li): var = li[index] print(var) index += 1 两次打印结果都一样: 1 2 3 4 5
3,for实现原理
li = [1,2,3,4,5] li2 = iter(li) try: while True: var = next(li2) print(var) except StopIteration: pass 打印结果: 1 2 3 4 5
4,从可迭代对象生成一个迭代器
迭代器 = iter(可迭代对象)
下个值 = next(迭代器)
5,自定义迭代器
迭代器对象本身需要支持以下两种方法,它们一起构成迭代器协议:
iterator.__iter__() iterator.__next__()
取值:
next(iterator) iterator.__next__()
注意:如果迭代器值取完之后,会返回StopIteration 错误
四,模块
1,模块的导入
-
在python中,模块就是一个py文件,可以使用下面两种方法导入
import datetime from datetime import datetime (as this_datetime) 注意:datetiame是一个常用的时间处理模块
-
在同一目录下,可直接使用上面两种方法去导入
在不同目录下,需要使用 sys.path 添加路径sys.path.append('path')
-
import sys sys.path.append('/home/pyvip/pycharm/学员信息管理系统') import zcm zcm.func1() zcm.func2()
-
在python3中导入后,会在当前路径下生成一个pycache 文件夹
2,导入语法 与 导入路径
-
import 模块名
直接导入
使用时模块名.函数名()
-
import 模块名 as 新名字
导入以后,重新命名
使用新名字.函数名()
-
from 模块名 import 函数名
部分导入,导入模块内部的东西,而不要模块可以在模块里用一个变量 __all__控制被导入函数
__all__ = ['func1','func2'] def func1(): print('这是第一行') def func2(): print('这是第二行') def func3(): print('这是第三行')
from zcm import * func1() func2() 打印结果: 这是第一行 这是第二行
-
__name__
python会自动的给模块加上这个属性
如果模块是被直接调用的,则__name__ 的值是__main__
否则就是该模块的模块名
-
if __name__ == '__main__'
该语句可以控制代码在被其他模块导入时不被执行
def func1(): print('这是第一行') def func2(): print('这是第二行') def func3(): print('这是第三行') if name == 'main': print('不想被调用')
import zcm zcm.func1() 打印结果: 这是第一行
1,包概念:
把很多模块放到一个文件夹里面,就可以形成一个包
导包
import test.zcm test.zcm.func1() import test.zcm as t # test是文件夹,zcm是py文件 t.func1() from test import zcm zcm.func1() from test import zcm as t t.func1()
导入全部包 *
__all__ = ['zcm'] # 这句代码必须要写到init里面 from test import * zcm.func1()
导入包方法:
# 例子1 # 在包里面的 __init__文件里定义函数方法 def initfunc(): print('这是initfunc')
# 例子1 import pp # pp是包文件夹的名字 pp.initfunc() 打印结果: 这是initfunc
# 例子2 # 在包里面的 __init__文件里定义函数方法 __all__ = ['initfunc'] def initfunc(): print('这是initfunc')
# 例子2 form pp import * initfunc() 打印结果: 这是initfunc
2,包管理:
当把很多模块放在文件中时,为了方便引用包中的模块,引入了包管理
3,__init__.py
在包管理中,加入此模块,则包名可以直接通过属性访问的方式,访问此模块内的对象,文件内容可以为空
4,相对路径导入
在包管理中,可以通过. (一个点) 和 .. (两个点)分别来导入同层和上一层的模块