Batteries Included Philosophy - having a rich and versatile standard library which is immediately available, without making the user download separate packages.
1. datetime
Python处理时间和日期的标准库
1.1. 获取当前时间和日期 1 2 3 4 5 6 7 8 >>> from datetime import datetime >>> now = datetime.now()>>> nowdatetime.datetime(2020 , 7 , 4 , 10 , 7 , 8 , 512524 ) >>> print (now)2020 -07-04 10 :07:08.512524 >>> print (type (now))<class 'datetime .datetime '>
1.2. 获取指定日期和时间 1 2 3 >>> dt = datetime(2020 , 6 , 6 , 6 , 6 ) >>> print (dt)2020 -06-06 06:06:00
1.3. datetime转timestamp 在计算机中,时间的表示是相对于Epoch time来计算的。Epoch time: 也称Unix time,是1970年1月1号 00:00:00 UTC+00:00 的时间。当前时间就是相对于Epoch time的秒数。 全球各地计算机的任意时刻timestap都是相同的,这也就是为什么计算机的时间都是用timestamp表示了。
1 2 3 4 5 6 7 8 9 10 11 >>> dt = datetime(2020 , 6 , 6 , 6 , 6 )>>> print (dt)2020 -06-06 06:06:00 >>> dt.timestamp() 1591419960.0 >>> t = 1591419960.0 >>> print (datetime.fromtimestamp(t)) 2020 -06-06 06:06:00 >>> print (datetime.utcfromtimestamp(t)) 2020 -06-06 05:06:00
1.4. str转datetime 1 2 3 >>> day = datetime.strptime('2020-06-06 06:06:00' , '%Y-%m-%d %H:%M:%S' ) >>> print (day)>>> 2020 -06-06 06:06:00
1.5. datetime转str 1 2 3 >>> now = datetime.now()>>> print (now.strftime('%a, %b %d %H:%M' ))Sat, Jul 04 10 :40
1.6. datetime加减 1 2 3 4 5 6 7 8 9 10 >>> from datetime import datetime, timedelta >>> now = datetime.now()>>> nowdatetime.datetime(2020 , 7 , 4 , 10 , 44 , 24 , 184738 ) >>> now + timedelta(hours = 12 )datetime.datetime(2020 , 7 , 4 , 22 , 44 , 24 , 184738 ) >>> now - timedelta(days=1 )datetime.datetime(2020 , 7 , 3 , 10 , 44 , 24 , 184738 ) >>> now + timedelta(days = 1 , hours = 12 )datetime.datetime(2020 , 7 , 5 , 22 , 44 , 24 , 184738 )
1.7. 本地时间转UTC 目前本地时间为英国夏时令(UTC+1)。datetime类型有一个时区属性tzinfo,默认为None。
1 2 3 4 5 6 7 8 9 10 >>> from datetime import datetime, timedelta, timezone>>> tz_utc_1 = timezone(timedelta(hours = 1 )) >>> now = datetime.now()>>> nowdatetime.datetime(2020 , 7 , 4 , 10 , 53 , 38 , 549365 ) >>> dt = now.replace(tzinfo = tz_utc_1) >>> dtdatetime.datetime(2020 , 7 , 4 , 10 , 53 , 38 , 549365 , tzinfo=datetime.timezone(datetime.timedelta(seconds=3600 ))) >>> print (dt)2020 -07-04 10 :53 :38.549365 +01:00
1.8. 时区转换 1 2 3 4 5 6 >>> utc_dt = datetime.utcnow().replace(tzinfo = timezone.utc) >>> print (utc_dt)2020 -07-04 10 :00 :56.720584 +00 :00 >>> bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8 ))) >>> print (bj_dt)2020 -07-04 18 :00 :56.720584 +08:00
1.9. tips datetime表示的时间需要时区信息才能确定一个时间,否则只能视为本地时间。 如果要存储datetime,最佳方法为timestamp,这样就与时区无关了。
2. collections
Python内建的集合模块
2.1. namedtuple - tuple的一个子类,既可以用下标访问也可以使用自定义的属性来访问 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 >>> from collections import namedtuple>>> Point = namedtuple('Point' , ['x' , 'y' ]) >>> p = Point(1 ,2 )>>> p.x1 >>>p[0 ] 1 >>> p.y2 >>> isinstance (p, Point)True >>> isinstance (p, tuple )True >>> Stu = namedtuple('Student' , ['name' , 'age' ])>>> s = Stu('Bob' , '20' )>>> sStudent(name='Bob' , age='20' ) >>> s.name'Bob'
2.2. deque
由于list为线性存储,数据量很大时,插入和删除的效率会很低。deque是为了实现插入和删除操作的双向列表,适用于队列和栈。
1 2 3 4 5 6 7 8 9 10 >>> from collections import deque>>> q = deque(['a' , 'b' , 'c' ])>>> q.append('x' )>>> q.appendleft('y' )>>> qdeque(['y' , 'a' , 'b' , 'c' , 'x' ]) >>> q.popleft()'y' >>> qdeque(['a' , 'b' , 'c' , 'x' ])
2.3. defaultdict
使用dict时,如果引用的Key不存在,就会抛出KeyError。使用defaultdict使得程序不抛错误,返回一个默认值。
1 2 3 4 5 6 7 8 9 10 11 >>> from collections import defaultdict>>> dd = defaultdict('Key not exit' )Traceback (most recent call last): File "<input>" , line 1 , in <module> TypeError: first argument must be callable or None >>> dd = defaultdict(lambda : 'Key not exit' ) >>> dd['name' ] = 'Bob' >>> dd['name' ] 'Bob' >>> dd['age' ] 'Key not exit'
2.4. OrderedDict OrderedDict:保持key的顺序; 不过在python 3.6之后,普通dict也是有序的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import collectionsprint ('\nRegular dictionary:' )d = {} d['a' ] = 'A' d['b' ] = 'B' d['c' ] = 'C' for k, v in d.items(): print (k, v) print ('\nOrderedDict:' )d = collections.OrderedDict() d['a' ] = 'A' d['b' ] = 'B' d['c' ] = 'C' for k, v in d.items(): print (k,v) Regular dictionary: a A b B c C OrderedDict: a A b B c C
2.5. ChainMap
可以将多个字典映射组合在一起,组成一个逻辑上的dict,maps中存储字典组成的列表。查找的时候,会按照dict中的逻辑顺序查找。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 >>> from collections import ChainMap>>> a = {"name" : "Bob" }>>> b = {"age" : 18 }>>> c = {"gender" : "man" }>>> pylook = ChainMap(a,b,c) >>> pylookChainMap({'name' : 'Bob' }, {'age' : 18 }, {'gender' : 'man' }) >>> pylook['name' ] 'Bob' >>> pylook.update({'name' : 'Mack' }) >>> pylook ChainMap({'name' : 'Mack' }, {'age' : 18 }, {'gender' : 'man' }) >>> pylook.update({'age' : '20' }) >>> pylookChainMap({'name' : 'Mack' , 'age' : '20' }, {'age' : 18 }, {'gender' : 'man' }) >>> b['age' ] = 22 >>> pylookChainMap({'name' : 'Mack' , 'age' : '20' }, {'age' : 22 }, {'gender' : 'man' }) >>> type (pylook.maps) <class 'list '> >>> pylook .maps [0]['age '] = 25 >>> pylook .maps [1]['age '] = 35 >>> pylook .maps [{'name ': 'Mack' , 'age' : 25 }, {'age' : 35 }, {'gender' : 'man' }]>>> pylook['age' ] 25 >>> pylook.parents ChainMap({'age' : 35 }, {'gender' : 'man' })
应用:
1 2 3 import builtinspylookup = ChainMap(locals (), globals (), vars (builtins))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 from collections import ChainMapimport os, argparsedefaults = { 'color' : 'red' , 'user' : 'guest' } parser = argparse.ArgumentParser() parser.add_argument('-u' , '--user' ) parser.add_argument('-c' , '--color' ) namespace = parser.parse_args() print (vars (namespace).items())command_line_args = {k: v for k, v in vars (namespace).items() if v} combined = ChainMap(command_line_args, os.environ, defaults) print ('color=%s' % combined['color' ])print ('user=%s' % combined['user' ])---------- (venv3.7 ) ➜ python test5.py dict_items([('user' , None ), ('color' , None )]) color=red user=guest (venv3.7 ) ➜ python test5.py -u Aaron dict_items([('user' , 'Aaron' ), ('color' , None )]) color=red user=Aaron (venv3.7 ) ➜ user=admin color=red python test5.py -u Aaron dict_items([('user' , 'Aaron' ), ('color' , None )]) color=red user=Aaron
2.6. Counter -计数器 1 2 3 4 5 6 7 8 9 >>> from collections import Counter>>> c = Counter('hello, word!' )>>> cCounter({'l' : 2 , 'o' : 2 , 'h' : 1 , 'e' : 1 , ',' : 1 , ' ' : 1 , 'w' : 1 , 'r' : 1 , 'd' : 1 , '!' : 1 }) >>> c.update('aaaaaa' ) >>> cCounter({'a' : 6 , 'l' : 2 , 'o' : 2 , 'h' : 1 , 'e' : 1 , ',' : 1 , ' ' : 1 , 'w' : 1 , 'r' : 1 , 'd' : 1 , '!' : 1 }) >>> c.get('a' ) 6
3. hashlib - 摘要算法
摘要算法:就像是一篇文章的摘要一样,永远不会变。摘要算法又称哈希算法、散列算法。它是通过一个函数把任意长度的数据转换为固定长度的数据串。只要原始数据没有发生改变,那么生成的数据串也不会变。Python的hashlib提供了常见的摘要算法,如:MD5,SHA1等等。摘要算法一般应用于防篡改。
3.1. MD5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 >>> import hashlib>>> md5 = hashlib.md5()>>> md5.update('hello, world!' .encode('utf-8' )) >>> md5.hexdigest()'3adbbad1791fbae3ec908894c4963870' >>> md5<md5 HASH object @ 0x10dec70c0 > >>> md5 = hashlib.md5()>>> md5>>> <md5 HASH object @ 0x10dec7600 >>>> md5.update('hello, ' .encode('utf-8' ))>>> md5.update('world!' .encode('utf-8' ))>>> md5.hexdigest()'3adbbad1791fbae3ec908894c4963870' >>> md5 = hashlib.md5()>>> md5.update('Hello, world!' .encode('utf-8' ))>>> md5.hexdigest()'6cd3556deb0da54bca060b4c39479839'
3.2. SHA1
SHA1算法和MD5使用方法类似,不过生成的摘要更长,摘要越长越安全,但算法会越慢
1 2 3 4 5 >>> import hashlib>>> sha1 = hashlib.sha1()>>> sha1.update('hello, world!' .encode('utf-8' ))>>> asha1.hexdigest()'1f09d30c707d53f3d16c530dd73d70a6ce7596a9'
3.3. Salt(加盐) md5(password+’the-salt ‘): 这样黑客在不知道’the-salt’ 的情况下,是很难通过MD5反推明文的。不过为了避免两个用户使用了相同的password后生成相同的MD5值,在确定用户无法修改登录名的情况下,会将部分用户名作为’the-salt’的一部分,这样就能保证相同口令的用户存储成不同的MD5值。
4. hmac
Hmac算法:Keyed-Hashing for Message Authentication,通过一个标准算法,把key混入计算过程中,代替我们的salt算法,可以使得算法更加标准化。
1 2 3 4 5 6 7 8 >>> import hmac>>> message = b'Hello, world!' >>> key = b'secret' >>> h = hmac.new(key, message, digestmod='MD5' )>>> h<hmac.HMAC object at 0x1087f71d0 > >>> h.hexdigest()'fa4ee7d173f2d97ee79022d1a7355bcf'
5.1. count() - 无限迭代器 1 2 3 4 5 6 7 8 9 >>> import itertools>>> nums = itertools.count(1 ) >>> for n in nums:... print (n)... 1 2 3 ...Ctrl + c
5.2. cycle() - 将传入的序列无限循环 1 2 3 4 5 6 7 8 9 >>> sequence = itertools.cycle('abc' )>>> for c in sequence:... print (c)... a b c a ...Ctrl + c
5.3. repeat() -提供参数限制重复次数 1 2 3 4 5 6 7 >>> ns = itertools.repeat('ab' , 3 )>>> for n in ns:... print (n)... ab ab ab
5.4. takewhile() - 在无限迭代中设置结束条件 1 2 3 4 5 6 >>> nums = itertools.count(1 )>>> ns = itertools.takewhile(lambda x: x < 4 , nums)>>> ns<itertools.takewhile object at 0x1087e1d70 > >>> list (ns)[1 , 2 , 3 ]
5.5. chain() - 串联一组迭代对象,形成更大的迭代器 1 2 3 4 5 6 7 >>> for c in itertools.chain('AB' , 'YZ' ):... print (c)... A B Y Z
5.6. groupby() - 把迭代器中相邻的重复元素提取出来 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 >>> for key, group in itertools.groupby('AAABBCAA' ):... print (key, list (group))... A ['A' , 'A' , 'A' ] B ['B' , 'B' ] C ['C' ] A ['A' , 'A' ] >>> for key, group in itertools.groupby('AaaBbCaA' , lambda c: c.upper()): ... print (key, list (group))... A ['A' , 'a' , 'a' ] B ['B' , 'b' ] C ['C' ] A ['a' , 'A' ]