「Python 基础」常用模块
Posted Aurelius-Shu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「Python 基础」常用模块相关的知识,希望对你有一定的参考价值。
文章目录
1. 内建模块
内建模块
,无需安装和配置即可使用;
datetime
处理日期和时间的模块;
# 前一个 datetime 是模块,后一个是类
from datetime import datetime
now()
>>> datetime.now()
datetime.datetime(2020, 11, 22, 10, 42, 2, 59763)
datetime()
>>> dt = datetime(2020, 11, 22, 10, 30)
>>> dt
datetime.datetime(2020, 11, 22, 10, 30)
timestamp
1970 年 1 月 1 日 00:00:00 UTC+00:00 时区的时刻为epoch time
(新纪元时间),当前时间是相对于epoch time
的秒数,称为timestamp
;
timestamp
的值与时区无关;
>>> dt = datetime(2020, 11, 22, 10, 30)
# datetime 转 timestamp
>>> t = dt.timestamp()
# timestamp 转 datetime 本地时间
>>> dt = datetime.fromtimestamp(t)
# timestamp 转 datetime utc 时间
>>> dt_utc = datetime.utcfromtimestamp(t)
strptime()
str
转datetime
时间格式;
>>> cday = datetime.strptime('2020-11-22 10:20:20', '%Y-%m-%d %H:%M:%S')
strftime()
datetime
转 str
;
>>> datetime.now().strftime('%a,%b %d %H:%M')
'Sun,Nov 22 11:38'
timedelta
>>> from datetime import timedelta
# 减 2天 2 小时
>>> datetime.now() - timedelta(days=2, hours=2)
datetime.datetime(2020, 11, 20, 9, 41, 8, 544137)
timezone
通过 timedelta
创建 timezone
;
>>> from datetime import timezone
# 创建时区 UTC+8:00
>>> tz_utc_8 = timezone(timedelta(hours=8))
>>> dt = datetime.now()
# 强制设置时区 为 UTC+8
>>> dt = dt.replace(tzinfo=tz_utc_8)
datetime.datetime(2020, 11, 22, 12, 4, 41, 559771, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800)))
时区转换
utcnow()
可以获得当前 UTC 时间,给 UTC 时间设置好时区后,利用 astimezone()
可以转换任意时区的时间;
>>> utc_now = datetime.utcnow().replace(tzinfo=timezone.utc)
>>> utc_8_now = utc_now.astimezone(timezone(timedelta(hours=8)))
>>> utc_9_now = utc_8_now.astimezone(timezone(timedelta(hours=9)))
不是必须从 UTC+0:00 时区转换到其他时区,任何带有时区的时间都可以正确的转换;
collections
内建模块集合;
namedtuple()
namedtuple()
可以用来创建一个 tuple
对象,并规定 tuple
元素的个数,从而使用属性而不是索引的方式应用元素;
>>> rom collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(1, 2)
>>> p.x
1
>>> p[0]
1
Point
对象是 tuple
对象的子类;
deque
实现来高效插入和删除(相对 list,list 是线性存储)的双向列表;
>>> from collections import deque
>>> q = deque(['a', 'b', 'c'])
>>> q.append('x')
>>> q.appendleft('y')
>>> q
deque(['y', 'a', 'b', 'c', 'x'])
append 和 pop 操作列表的末尾;
appendleft 和 popleft 操作列表的开头;
defaultdict
含默认值的dict
,与dict
的使用相同;
>>> from collections import defaultdict
# 默认值使用函数设置
>>> dd = defaultdict(lambda :'N/A')
>>> dd['key']
'N/A'
OrderedDict
以Key
插入的顺序排序的dict
;
>>> OrderedDict(a=1, b=2, c=3)
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
FIFO
from collections import OrderedDict
class LastUpdatedOrderedDict(OrderedDict):
def __init__(self, capacity):
super(LastUpdatedOrderedDict, self).__init__()
self._capacity = capacity
def __setitem__(self, key, value):
containKey = 1 if key in self else 0
print(len(self))
if len(self) - containKey >= self._capacity:
last = self.popitem(last=False)
print('remove:', last)
if containKey:
del self[key]
print('set:', (key, value))
else:
print('add:', (key, value))
OrderedDict.__setitem__(self, key, value)
ChainMap
将多个dict
对象串起来,在查找的时候,实际按照内部dict
顺序一次查找;
from argparse import Namespace
from collections import ChainMap
import os, argparse
defauts = 'user': 'guest', 'color': 'red'
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = k: v for k, v in vars(namespace).items() if v
# 查找时,现在 command_line_args 中查找,如果没有,再在 os.environ 查找,最后时 defaults
combined_args = ChainMap(command_line_args, os.environ, defauts)
print('color=%s' % combined_args['color'])
print('user=%s' % combined_args['user'])
Counter
计数器,实际也是一个dict
子类;
from collections import Counter
c = Counter
# 手动统计
for ch in 'programing':
c[ch]=c[ch]+1
# 自动添加
c.update('hello')
base64
Base64
是一种任意二进制到文本字符串的编码方法,常用于小段URL
,Cookie
,数字签名等;
对二进制数据,每 3 字节一组,按没 6 bit 分为 4 组,从 64 个预设好的字符找到对应编码,不足 3 字节的末尾加一个或两个\\x00
,再在编码后的末尾加上 1 或 2 个=
标记,解码时自动去掉;
>>> import base64
>>> base64.b64encode(b'binary\\x00string')
b'YmluYXJ5AHN0cmluZw=='
>>> base64.b64decode(b'YmluYXJ5AHN0cmluZw==')
b'binary\\x00string'
# 对比 urlsafe,将 + 和 / 分别变成 - 和 _
>>> base64.b64encode(b'i\\xb7\\x1d\\xfb\\xef\\xff')
b'abcd++//'
>>> base64.urlsafe_b64encode(b'i\\xb7\\x1d\\xfb\\xef\\xff')
b'abcd--__'
>>> base64.urlsafe_b64decode(b'abcd--__')
b'i\\xb7\\x1d\\xfb\\xef\\xff'
url
中=
也需要去掉;
struct
用来处理bytes
与其他二进制数据的转换;
>>> n = 10240099
>>> b1 = (n & 0xff000000) >> 24
>>> b2 = (n & 0xff0000) >> 16
>>> b3 = (n & 0xff00) >> 8
>>> b1 = (n & 0xff)
>>> bs = bytes([b1, b2, b3, b4])
>>> bs
b'\\x00\\x9c@c'
>>> import struct
>>> struct.pack('>I', 10240099)
b'\\x00\\x9c@c'
>>> struct.unpack('>I', b'\\x00\\x9c@c')
10240099
-
>
,表示字节顺序是 big-endian,即网络序,I
表示 4 字节无符号整数;
hashlib
摘要算法
又叫哈希算法,散列算法,通过一个函数,把任意长度的数据转换成一个长度固定的数据串(通常是 16 进制字符串);
>>> import hashlib
>>> md5 = hashlib.md5()
# 可分多次调用 update
>>> md5.update('how to use md5 in '.encode('utf-8'))
>>> md5.update('python hashlib?'.encode('utf-8'))
# 提取 16 进制摘要
>>> print(md5.hexdigest())
d26a53750bc40b38b65a520292f69306
sha1
、sha256
、sha512
的调用方式与md5
完全一致,它们更加安全,但更慢,所得摘要更长;
碰撞
两个不同的数据通过某个摘要算法得到了相同的摘要,叫做碰撞,这是有可能的(因为任何摘要算法都是把无限的数据集合映射到有限的集合中);
摘要的应用
用于生成密文的口令存储于数据库;
经过混入salt
和唯一且不可修改的ID
,再求哈希值,这样存储会更安全;
摘要算法不是用来加密的,因为无法反推明文,只是用于防篡改的;
hmac
Keyed-Hashing for Message Authentication;
通过标准的算法,把key
混入计算过程;
>>> import hmac
>>> message = b'hello world'
>>> key = b'secret'
>>> h = hmac.new(key, message, digestmod='MD5')
# 如果 message 很长,可以分多次调用 h.update(msg)
>>> h.hexdigest()
'78d6997b1230f38e59b6d1642dfaa3a4'
itertools
用于操作迭代对象的函数;
count(n)
创建一个无限迭代器,起始于n
,每次加 1;
import itertools
# 自然数
natuals = itertools.count(1)
cycle(list)
创建一个无限迭代器,无限重复传入的序列;
# 无限重复'A','B','C'
cs = itertools.cycle('ABC')
repeat(item)
创建一个无限迭代器,无限重复传入的一个元素,第二个参数可以限定重复的次数;
ns = itertools.repeat(123, 3)
takewhile()
传入一个筛选函数,用来截取子序列;
与filter
不同,当函数条件第一次不满足后,不再继续迭代;
调用所得是一个 itertools.takewhile
迭代对象;
>>> ns = itertools.takewhile(lambda x: x<=10, natuals)
>>> list(ns)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
chain()
将一组迭代对象串联起来;
cn = itertools.chain('ABC', 'XYZ')
groupby()
把相邻的重复元素调出分到一组,group
是itertools._grouper
迭代对象;
>>> for key, group in itertools.groupby('aaabbbccaaa', lambda c: c.upper()):
... print(key, list(group))
...
A ['a', 'a', 'a']
B ['b', 'b', 'b']
C ['c', 'c']
A ['a', 'a', 'a']
可以传入一个函数座位第二参数,元素通过函数处理后再作用于groupby
;
圆周率
def pi(N):
' 计算pi的值 '
# step 1: 创建一个奇数序列: 1, 3, 5, 7, 9, ...
natuals = itertools.count(1)
odd = filter(lambda x: x % 2 > 0, natuals)
# step 2: 取该序列的前N项: 1, 3, 5, 7, 9, ..., 2*N-1.
odd = itertools.takewhile(lambda x: (x + 1) // 2 <= N, odd)
# step 3: 添加正负符号并用4除: 4/1, -4/3, 4/5, -4/7, 4/9, ...
items = map(lambda x: (4 / (x if (((x + 1) // 2) % 2 > 0) else (0 - x))),
odd)
# step 4: 求和:
return sum(items)
contextlib
只要实现了上下文管理,任何对象都可以使用with
语句;
__enter__ 和 __exit__
class Query(object):
def __init__(self, name):
self.name = name
def __enter__(self):
print('begin')
return self
def __exit__(self, exc_type, exc_value, traceback):
if exc_type:
print('Error')
else:
print('End')
def query(self):
print('query info about %s...' % self.name)
with Query('bob') as q:
q.query()
使用with
语句时,自动调用 __enter__ 和 __exit__;
@contextmanager
class Query2(object):
def __init__(self, name):
self.name = name
def query(self):
print('query info about %s...' % self.name)
@contextmanager
def create_query(name):
print('begin')
q = Query2(name)
yield q
print('end')
with create_query('bob') as q:
q.query()
with
语句会先执行yield
之前的语句,yield
调用会执行with
语句内部的语句,最后执行yield
之后的语句;
closing
closing
是一个经过@contextmanager
装饰的generator
;
@contextmanager
def closing(thing):
try:
yield thing
finally:
thing.close()
针对 Python 中读写资源使用完一定要正确关闭的问题,更简单的方式是使用 closing
;
from contextlib import closing
from urllib.request import urlopen
# closing 将 没有实现上下文管理的对象变为上下文对象
with closing(urlopen('https://www.python.org')) as page:
for line in page:
print(line)
urllib
用于操作URL
;
GET
from urllib import request
req = request.Request('http://dict.youdao.com/w/odd/#keyfrom=dict2.top')
# 模拟 iphone OS 8.0 发起请求
req.add_header(
'User-Agent',
'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (Khtml, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25'
)
with request.urlopen(req) as f:
data = f.read()
print('status:', f.status, f.reason)
for k, v in f.getheaders():
print(f'k: v')
print('data:'.data.decode('utf-8'))
POST
email = 'aaa.foxmail.com'
pwd = 'xxxxxx'
login_data = parse.urlencode([
('username', email), ('password', pwd), ('entry', 'mweibo'),
('client_id', ''), ('savestate', '1'), ('ec', ''),
('pagerefer',
'https://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F'
)
])
req = request.Request('https://passport.weibo.cn/sso/login')
# Origin 说明请求从哪里发起的,包括,且仅仅包括协议和域名
req.add_header('Origin', 'https://passport.weibo.cn')
# User-Agent 表示 HTTP 客户端程序的信息
req.add_header(
'User-Agent',
'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25'
)
# Referer 表示 请求中 URI 的原始获取方
req.add_header(
'Referer',
'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F'
)
# data 参数以 bytes 传入
with request.urlopen(以上是关于「Python 基础」常用模块的主要内容,如果未能解决你的问题,请参考以下文章