包和模块
生成器
如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在python中,这种一边循环一边计算的机制,称为生成器(Generator).
特点:
延迟计算、惰性求值
节省内存,高效
缺点:无法随机存取
生成器(Generator)生成器会产生一个对象,而不是一个列表
yield表达式
#通过函数和yield关键字生成
#使用了 yield 的函数被称为生成器(generator)
#yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行
def test(n):
for i in range(1,n + 1):
yield i
#print(i)
#得到生成器
result = test(10)
print(result)
#可以使用next函数获取下一个值
print(next(result))
#生成器只能遍历一次, 所以下面不会有任何输出
for x in result:
print(x)
#可以这样遍历
for x in test(10):
print(x)
生成器表达式
生成器【Generator 】生成器会产生一个可迭代对象,而不是一个列表。生成器表达式很类似列表生成式:
(表达式 for var in 可迭代对象)
#将列表生成式中的[]替换成()
ge = (x for x in range(1,6))
print(ge,type(ge))
#生成器需要通过next()无法获取数据,调用一次则返回一个数据
print(next(ge))
print(next(ge))
print(next(ge))
print(next(ge))
print(next(ge))
#注意:如果通过next函数获取生成器中的数据,当数据取完之后,
#将不能再调用next函数,否则出现StopIteration
#print(next(ge)) #StopIteration
#生成器主要通过for-in的方式进行遍历
for x in ge:
print(x,end=' ')
迭代器
迭代对象
可以直接作用于for-in循环的数据类型都被成可迭代对象,可以使用isinstance()判断一个对象是否可迭代对象,可以直接作用于for-in循环的数据类型:
数据结构:list、set、tuple、dict、string
generator【生成器】【(),函数结yield】
#引入 from collection import Iterable
from collections import Iterable
print(isinstance("",Iterable))#True
print(isinstance({},Iterable))#True
print(isinstance((),Iterable))#True
print(isinstance(1,Iterable))#Fals
迭代器
迭代器不但可以作用于for-in循环,还可以使用next()函数将其中的元素获取出来,当获取完最后一个元素之后,当再次调用next方法,则会出现StopIteration错误,表示无法继续返回一个值。可以使用isinstance()判断一个对象是否是迭代器。迭代器的类型是Iterator
from collections import Iterator,Iterable
print(isinstance([],Iterator)) #False
print(isinstance((),Iterator)) #False
print(isinstance({},Iterator)) #False
print(isinstance("",Iterator)) #False
print(isinstance((x for x in range(0,6)),Iterator)) #True 生成器是迭代器
print(isinstance((x for x in range(0,6)),Iterable)) #True 生成器也是迭代对象
结论:list、set、tuple、dict、string是可迭代对象,但是,不是迭代器,只有生成器才是迭代器
将迭代对象转换为迭代器
迭代器一定是可迭代对象,但是,可迭代对象不一定是迭代器
inter():将可迭代对象转化为迭代器【主要针对list,set,tuple,dict,string】
print(isinstance(iter([]),Iterator)) #True
print(isinstance(iter(()),Iterator)) #True
print(isinstance(iter({}),Iterator)) #True
print(isinstance(iter(""),Iterator)) #True
l2 = iter(l1) #将列表转换为迭代器
print(next(l2)) #使用next获取迭代器中的元素
while True:
try:
print(next(l2)) #可能出问题的代码放到try块中
except StopIteration: #捕获异常
break #终止循环
包
包是为了解决模块重名问题,python引入了以目录方式组织模块,称之为包(package),一个包中可以包含模块,包。
目录和包的区别
python的包中必须包含一个特殊文件,被命名为_init_.py,这文件告诉解释权这是一个包,而目录不要求一定要有,这是目录和包的区别;另外可以使用import导入包中的模块,但目录不行。
模块
在python中,模块是代码组织的一种方式,把功能相近的函数放到一个文件中,一个文件(.py)就是一个模块(module),模块名就是文件名去掉后缀py。这样做的好处是:
提高代码的可复用,可维护性,一个模块编写完毕后,可以方便的在其他项目中导入
解决了命名冲突,不同模块中相同的命名不会冲突
常用标准库:
标准库 | 说明 |
---|---|
builtins | 内建函数默认加载 |
math | 数学库 |
random | 生成随机数 |
time | 时间 |
datime | 日期和时间 |
calendar | 日历 |
hashlib | 加密算法 |
copy | 拷贝 |
functools | 常用的工具 |
os | 操作系统接口 |
re | 字符串正则匹配 |
sys | python自身的运行环境 |
mulyiprocessing | 多进程 |
threading | 多线程 |
json | 编码和解码json对象 |
logging | 记录日志,调试 |
模块搜索路径
当导入一个模块时,解释器先在当前包中查找模块,若找不到,然后在内置的
built-in模块中查找,找不到则按sys.path给定的路径找对应的模块文件(模块名.py)
import sys
#sys.path是一个列表
print(sys.path)
#可以使用列表的方法,增加搜索路径
sys.path.append(r'c:\wh1803')
导入模块
可以使用import语句导入模块,格式:
#1基本语法
import 包名.模块名1
import 包名.模块名2
....
import 包名.模块名n
#或者一行导入多个,不建议这么些,可读性不好
import 模块1,模块2,....模块n
#2 使用from...import导入指定标识符,语法:
from module import name1 [,name2 [,name3...[,namen]]]
from module imort * #导入模块中所有标识符,不建议使用
#3.可是使用as给模块起一个别名
import 模块名 as 别名
import语句的模块顺序,推荐在文件开头导入模块,建议按照如下顺序:
python标准库
第三方库
自定义库
这三类库中间添加一个空行, 模块第一次被导入的时候会被执行。如果在导入模块执行模块中代码,可以使用_name_属性进行判断,如果该模块是当前模块不是导入模块,name_的值是_main.所以可以这样检测:
#hello.py
def test()
print('test')
if __name__ == '__main__' #执行的是当前模块,则为真;导入的模块则为假
test()
日期时间模块
datetime:日期
time :时间
calendar:日历
时间间隔是以秒为单位的
每个时间戳都以自从1970.1.1经历了多长时间计算的
时间戳:当前时间距离1970.1.1的秒数
time时间模块
时间的表示形式:
a.以整数或者浮点数表示一个以秒为单位的时间间隔,这个时间的基础值
1970.1.1的零时零分零秒
b.采用Python中的数据结构表示,采用元组,元组中可以有9个不同的元素,表示不同的含义
c.格式化的时间字符串
符号 | 说明 |
---|---|
%a | 本地(locale)简化星期名称 |
%A | 本地完整星期名称 |
%b | 本地简化月份名称 |
%B | 本地完整月份名称 |
%c | 本地相应的日期和时间表示 |
%d | 一个月中的第几天 |
%H | 一天中的第几个小时(24小时制,00-23) |
%l | 第几个小时(12小时制,01-12) |
%j | 一年中第几天(001-366) |
%m | 月份(01-12) |
%M | 分钟数(00-59) |
%p | 本地am或者pm的相应符 |
%S | 秒(01-61) |
%U | 一年中的星期数 |
%w | 一个星期中的第几天 |
%W | 和%U基本相同,不同的是%W以星期一为一个星期的开始 |
%x | 本地相应日期 |
%X | 本地相应时间 |
%y | 去掉世纪的年份 |
%Y | 完整的年份 |
%Z | 时区的名字(如果不存在为空字符) |
%% | ‘%’字符 |
获取当前时间的时间戳
c = time.time() #*********
print(c) #时间的第一种表示形式,时间戳:1522635821.4109497
将上述时间戳转换为时间元组
g = time.gmtime(c)
print(g)
#time.struct_time(tm_year=2018, tm_mon=4, tm_mday=2, tm_hour=2,
tm_min=25, tm_sec=33, tm_wday=0, tm_yday=92, tm_isdst=0)
将时间戳生成时间元组(本地时间)
l = time.localtime(c) #*********
print(l)
#time.struct_time(tm_year=2018, tm_mon=4, tm_mday=2, tm_hour=10,
tm_min=27, tm_sec=13, tm_wday=0, tm_yday=92, tm_isdst=0)
将时间元组转换为时间戳
c2 = time.mktime(l)
print(c2)
c3 = time.mktime((2018,4,2,10,29,23,3,320,0))
print(c3)
将时间戳转换为字符串
c4 = time.ctime(c3)
print(c4) #Mon Apr 2 10:29:23 2018
将时间元组转换为格式化字符串
#注意:必须严格按照格式化的形式书写字符串【严格区分大小写】
s = time.strftime("%Y-%m-%d %H:%M:%S",l) #*********
print(s) #2018-04-02 10:35:45
7.将指定格式的时间字符串转换为时间元组
#参数1:指定的时间 参数2:指定的时间格式
p = time.strptime("2018-04-02 10:35:45","%Y-%m-%d %H:%M:%S")
print(p)
#time.struct_time(tm_year=2018, tm_mon=4, tm_mday=2, tm_hour=10,
tm_min=35, tm_sec=45, tm_wday=0, tm_yday=92, tm_isdst=-1)
休眠【暂停】
#参数的单位为秒
#time.sleep(5) #*********
用来衡量不同程序的耗时
print(time.clock()) #*********
#time\localtime\strftime\sleep\clock
#练习:假如我有一个时间字符串,然后向得到这个字符串所对应时间3天之后的
时间
#2017.5.7
time1 = "2017-5-7"
将时间转换为元组
p1 = time.strptime(time1,"%Y-%m-%d")
print(p1)
将元组转换成时间戳
t1 = time.mktime(p1)
t3 = t1 + 3 * 24 * 3600
#最终转换为格式化形式
f = time.strftime("%Y.%m.%d",time.localtime(t3))
print(f)
datetime日期模块
datetime比time更加高级。是对time进行了封装
获取当前时间
import datetime
d1 = datetime.datetime.now()
print(d1)
获取指定时间
d2 = datetime.datetime
print(d2)
将指定时间转换为字符串
d4 = d1.strftime('%Y-%m-%d)
print(d4)
print(type(d4)
d5 = datetime.datetime.strptime(d4,"%Y-%m-%d")
print(d5)
两个时间相减,可以得到时间间隔
d6 = datetime.datetime(2018,4,2,10,56,00,3623)
d7 = datetime.datetime(2018,4,5,10,56,32,3623)
d8 = d7 - d6
print(d8) #3 days, 0:00:00
print(d8.days)
整数天之外的秒数
print(d8.seconds)
timedelta
datetime.timedelta对象代表两个时间之间的时间差,两个date或datetime对象相减就可以返回一个timedelta对象
import datetime
t1 = datetime.datetime.now()
t2 = datetime.timedelta(days=1)
result = t1 + t2 # 获取一天后的时间
print(result)
result = t1 - t2 # 获取一天的时间
print(t2.total_seconds()) # 获取总秒数
calendar日历模块
主要用于获取日历的相信信息
直接返回指定年和月的万年历表示形式
print(calendar.month(2018,4))
返回万年历的二维列表表示形式
print(calendar.monthcalendar(2018,4))
.直接返回指定年份的万年历表示形式
print(calendar.calendar(2018))
判断某年是否为闰年
print(calendar.isleap(2010)) #********
print(calendar.leapdays(2000,2020))
返回指定月的weekday的第一天和这个月的所有的天数
print(calendar.monthrange(2018,4)) #(6, 30)---》(当月开始的第一天为星期几,mon为0,第二个元素表示当月的总天数
print(calendar.monthcalendar(2018,4))
当前日期表示的星期数
print(calendar.weekday(2018,4,2))