生成器
- 概念 使用yield的函数叫生成器(generator),在调用生成器的过程中,当碰到yield时,函数会停止执行并保存当前所有运行信息,并且返回yield的值。下一次执行next()方法时继续从当前位置运行。
- 作用 不需要完全运行完毕,而是先运行一次,需要时再运行一次。具有延迟计算、惰性求值、节省内存,⾼效利用内在的作用,同时不像别的列表等序列会直接生成所有元素,因此在节省内存的同时也存在⽆法随机存取的缺点。
- 定义:
def test(n):
for x in range(1,n+1):
yield x
- 调用:
a = test(5)
# 使用next()调用
print(next(a)) # 1
print(next(b)) # 2
# 使用for in 遍历
for i in test(5):
print(i)
- 辨析
上例中,如调用时采用以下内容返回结果与上面不同,原因是print(test(5)),print(test(5))调用了两个生成器,因此返回都是1
print(test(5)) # 1
print(test(5)) # 1
- 生成器表达式
类似列表推导式x=[i for i in range(0,5)],x是生成的列表。如果是x=(i for i in range(0,5)),x就是一个生成器了,使用next()方法运行下一次,或者使用for…in遍历
x = (i for i in range(0,5))
print(next(x)) #0
print(next(x)) #1
for z in x:
print(z) # 0,1,2,3,4
迭代器
可以直接使用for…in的数据类型都叫可迭代对象
迭代器不仅可以用for…in遍历,还可以用next()获取其中的元素
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
字符串,列表或元组对象都可用于创建迭代器.
- 判断迭代对象
from collections import Iterable
isInstance(a,Iterable) # a是否可迭代对象
- 判断迭代器
from collections import Iterator
isInstance({},Iterator) #False
isInstance((x for x in range(0,5)) # True
结论:list、set、tuple、dict、string是可迭代对象,但是,不是迭代器,只有⽣成器才是迭代器
- 将迭代对象转化为迭代器
迭代器⼀定是可迭代对象,但是,可迭代对象不⼀定是迭代器
iter():将可迭代对象转化为迭代器【主要针对list、set、tuple、dict、string】
print(isinstance(iter([]),Iterator)) #True
包
包是为了解决模块重名问题,python引⼊了以⽬录⽅式组织模块,称之为包package),⼀个包中可以包含模块、包。python的包中必须包含⼀个特殊⽂件,被命名为__ init__.py,这⽂件告诉解释器这是⼀个包,⽽⽬录则不要求⼀定要有,这是⽬录和包的区别;另外可以使⽤import导⼊包中的模块,但⽬录不⾏。
包名和模块名通常为全部小写,避免使用下划线。
模块
在python中,模块是代码组织的⼀种⽅式,把功能相近的函数放到⼀个⽂件中,⼀个⽂件(.py)就是⼀个模块(module),模块名就是⽂件名去掉后缀py。这样做的好处是:
提⾼代码的可复⽤、可维护性。⼀个模块编写完毕后,可以很⽅便的在其他项⽬中导⼊解决了命名冲突,不同模块中相同的命名不会冲突。
常⽤标准库:
模块搜索路径
当导⼊⼀个模块时,解释器先在当前包中查找模块,若找不到,然后在内置的built-in模块中查找,找不到则按sys.path给定的路径找对应的模块⽂件(模块名.py)
导入方法
import 包名.模块
from module import name1
from module import *
import module as 别名
导入时,会自动执行被导入模块中的可执行代码。如果不想执⾏,可以在被导入模块中使⽤__ name__ 属性进⾏判断,如果该模块是当前模块,不是导⼊模块,name __ 的值是__main
def abc(a):
print(a.upper())
if __name__ == '__main__': # 2.所以有这句话表示只有非导入状态才执行下面的语句
abc("abcdefg") # 否则如果被导入,会自动执行本语句