Python内置了很多模块,这些模块往往很有用.
处理时间和日期–datetime
1.获取当前的时间–以datetime对象方式返回
1 | from datetime import datetime |
2.获取指定时间和日期,直接像构造一个datetime对象就行了.
1 | time = datetime(2018,4,10,13,21,0) |
3.时间戳
为了解决不同时区的时间不同的问题,时间戳成为了统一全球的时间表达方式,并且,这也成为了计算机保存时间的统一方式.
至于时间戳为什么能够达到统一,来看这个例子.
1 | timestamp = 0 = 1970-1-1 00:00:00 UTC+0:00 //标准时间 |
所以说,timestamp和时区根本就没有关系,只要timestamp定下来,其UTC时间就定下来了,转换到任意时区的时间也是完全固定的.在时间校准的情况下,全球各地的计算机在任意时刻的时间戳都是相同的.
将一个datetime对象转换为时间戳形式很简单.
直接调用timestamp()来构造一个浮点型的时间戳.
注意:Python中的timestamp是一个浮点数,小数是指毫秒,你也许会问,为什么在JAVA,JavaScript中的时间戳是整数呢? 事实上,这些编程语言已经将其乘了1000.所以在表示时要注意进行转换.
反过来,将一个timestamp转换成为datetime只要调用datetime的fromtimestamp()方法即可.
4.字符串与时间的计算和转换
转换的过程事实上是相似的,如同其他语言,都要使用格式化符号来表示年份,星期,月,日和具体的时间.
字符串转datetime
1 | cday = datetime.strptime('2018-6-1 18:19:59', '%Y-%m-%d %H:%M:%S') |
datetime转字符串
1 | current = now.strftime("%a, %b %d %H:%M") |
时间的加减
由于计算机是使用的时间戳来存储的时间,那么就可用+或-来进行运算.
但是,如果为了更好地迁移,可以使用这样的模块timedelta.
例如:
1 | from datetime import datetime, timedelta, timezone |
你会发现,我多import进来了一个timezone.
这个部件可将时间进行UTC时间的转换.
如:
1 | zone = timezone(timedelta(hours=8)) |
如果需要UTC时间,可以直接调用datetime.utcnow()
交换时区除了通过datetime对象的replace方法强制更改外,带有时区属性的datetime通过astimezone()方法,来进行转换.
比如:
1 | utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc) |
如果在获取datetime对象时,没有指定时区,就会被视作本地时间.
所以,不如使用timestamp来存放datetime对象.
collections
见名知意,内建的集合模块,封装了很多有用的集合类
主要有:namedtuple,deque,defaultdict, OrderedDict, Counter….
namedtuple:
假使我们构建一个元组:
1 | q = (1,2) |
并不能知道这个元组是干什么用的,在这种情况下,就到了namedtuple登场的时候了:
1 | Point = namedtuple("Point", ['x', 'y']) |
这样对象就得到了很好的管理,做个试验吧:
1 | isinstance(p,Point) |
deque:
双向队列,如同其他的语言,deque具有append(),pop(),还支持appendleft()和popleft().
例如:
1 | //导入 |
defaultdict:
专用来处理访问dict不存在key的一种方法.
1 | dd = default(lambda: 'N/A') //default |
defaultdict,也可这样使用:
1 | ldict = collections.defaultdict(list) |
这样生成的,ldict就会变成子元素都是list的一个defaultdict了.
而defaultdict又是dict的子类,所以这个对象会变得非常灵活.(感觉上有点像泛型,虽然他们有质的区别)
OrderDict
我们都知道,dict的排列顺序是随机的,Key是无序的.
为了能够在迭代时确认Key的顺序,我们便使用OrderDict
Counter
Counter是一个简单的计数器,但他的用法却可以很灵活
比如:
1 | from collections import Counter |
c的输出为Counter({'l':3, 'o':2, .....})
base64
先来简要介绍一下Base64编码的原理,Base64使用 a-z A-Z 0-9 + / 这64个字符来表示二进制数据(不计等号,等号是用来补空位的),由于,计算机内的编码方式是2进制,2^6=64,因此,便将6个比特映射到一个Base64可打印字符上,就可以进行转换了.
比如:man这个字符串,转为Base64编码的过程为:
| 文本 | M | A | N |
|---|---|---|---|
| ASCII | 77 | 97 | 110 |
ASCII转为二进制位:01001101 01100001 01101110
6比特分组:010011 010110 000101 101110
得到索引:19 22 5 46
查表进行Base64编码:T W F u
所以,Base64编码后的数据比原始数据略长,为原来的4/3.
到这里就出现问题了,如果我二进制数据的长度不是6的整数倍怎么办呢?
事实上,当原数据长度不是3的整数倍时, 如果最后剩下一个输入数据,在编码结果后加2个“=”;如果最后剩下两个输入数据,编码结果后加1个“=”;如果没有剩下任何数据,就什么都不加.
现在就可以来看一下Python对Base64的支持了.
1 | import base64 |
hashlib
hashlib是python的摘要算法模块,提供常见的摘要算法如:SHA,MD5等等
简单的说,摘要算法就是通过一个函数,把任意长度的数据转换为一个长度固定的数据串
只要源数据有一丁点的改变,摘要(digest)就会有翻天覆地的变化.所以经常用来进行软件或信息的检验.
摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。
md5d的摘要示例:
1 | import hashlib |
还可以使用更加安全的SHA算法,调用方法基本类似.
itertools
注意:当使用不当时.itertools极其容易无限迭代
因此做实验时建议考虑加上time.sleep()
拥有无限迭代的迭代器有:
count: 进行自增1的迭代
1 | import itertools, time |
输出:1 2 3 4 5 6 7.....
cycle: 进行循环迭代
1 | cycles = itertools.cycle("ABCD") |
输出: A B C D A B C D A....
repeat: 进行重复迭代(准确的说,这也可以不叫做无限迭代)
1 | repeats = itertools.repeat("A", 3) |
输出: A A A
一次迭代,迭代器就会失效!
为了结束无限循环,可以使用takewhile()来截断出一个有限的序列:
1 | naturals = itertools.count(1) |
再说两个经常用的函数:chain()和groupby()
例如:
1 | itertools.chain |
将两个迭代器进行拼接,也可以理解成是在拓展一个迭代器.
1 | for n in itertools.chain("ABC", "XYZ"): |
输出: "A","B","C","X","Y","Z"
1 | itertools.groupby() |
有点像数据库查询的GROUPBY..将元素分组,可以这样接受数据:
1 | for key,val in itertools.groupby("AaaBbbCcc", lambda x : x.upper()): |
只要后面函数的返回值相同,那么元素就被认为是同组的,这个返回的值就是元素的组名.
pickle
pickle这个模块负责进行对象的持久化,或者叫序列化.
一个对象的生命周期是不可能比一个Pyhton程序还长的,所以,为了使得这个对象在下次程序启动是仍能使用,pickle便提供了这样的接口.
pickle的核心API就是dump/dumps/load/loads这四个.
这是一个持久化的例子:
1 | import pickle |
将已序列化的对象复原:
1 | import pickle |