Python学习 之 高级模块

序列化模块

  • 数据类型 --> 字符串类型 称之为序列化
  • 字符串类型–> 数据类型 称之为反序列化

json - 所有语言通用

import json

dic = {'k':'v'}
strA = '{"k":"v"}'

# dumps 字典-->字符串
json.dumps(dic)

# loads 字符串-->字典
json.loads(strA)

'''单条数据'''
# dump 字典-->文件
with open(file, 'w') as f:
	json.dump(dic, f)

# load 文件-->字典
with open(file, 'r') as f:
	ret = json.load(f)
	print(ret)

'''多条数据'''
# 用dumps讲每条数据处理成字符串, 在末尾增加标识符, 在使用write方法写入文件
with open(file, "w") as f:
    for i in l:
        r = json.dumps(i)
        f.write(r+"\n")

# 使用for循环将每行字符串取出, 再用loads处理成字典
with open(file, 'r') as f:
	for line in f:
		ret = json.loads(line.strip()) # 去除首尾空格,并反序列化
		print(ret)

pickle - 只用于 python, 常用于存对象

import pickle

class Foo:
	def __init__(self, num):
		self.num = num

a = Foo(1)
# dumps 对象-->字符串
ret1 = pickle.dumps(a)

# loads 字符串-->对象
ret2 = pickle.loads(ret1)

'''单条数据'''
# dump 对象-->文件
with open(file, 'wb') as f:
	pickle.dump(a, f)

# load 文件-->对象
with open(file, 'rb') as f:
	pickle.load(f)

'''多条数据'''
# dump 对象-->文件
with open(file, 'wb') as f:
# dump 对象-->文件
with open(file, 'wb') as f:
	pickle.dump(a, f)	
	pickle.dump(b, f)	
	pickle.dump(c, f)	

# load 文件-->对象
while True:
	try:
		with open(file, 'rb') as f:
			ret = pickle.load(f)
			yield ret
	except EOFError:
		break		

re - 正则匹配

常规用法

  • 匹配
    import re
    
    # 示例字符串
    s = "a1b2a2e2g3t54a1"
    
    # findall, 返回列表, 包含所有结果
    r = re.findall(r"\d", s)
    print("findall result: ", r)                # ['1', '2', '2', '2', '3', '5', '4', '1']
    
    # finditer, 返回可迭代对象, 包含所有结果, 需要遍历后调用 group()方法取值, 若没有匹配成功则可迭代对象为空
    r = re.finditer(r"\d", s)
    for i in r:
        print(i.group())                        # 1, 2, 2, 2, 3, 5, 4, 1
    
    # search, 匹配符合条件的字符串, 返回第一个对象(group()取结果), 匹配不到返回none
    r = re.search(r"\d", s)
    if r:
        print("search result: ", r.group())     # 1
    
    # match, 匹配以条件开头的字符串, 返回第一个对象(group()取结果), 匹配不到返回none, 等价于 search(r"^...")
    r = re.match(r"\d", s)
    if r:                                       # none, 因为开头是字符不是数字
        print("match result: ", r.group())
    
    # fullmatch, 用于确认整个字符串是否符合正则要求, 不符合则返回 none
    s = "123456"
    flag = re.fullmatch(r"\d+", s)
    if not flag:
        exit("字符串不符合正则要求")
    
  • 分隔
    import re
    
    s = "a1a2a2a1"
    
    # 用匹配条件进行分隔, 返回分隔后的字符串, 不保留分隔符
    r = re.split(r"[12]", s)
    print(r)                            # ['a', 'a', 'a', 'a', '']
    
    # 用匹配条件进行分隔, 返回分隔后的字符串, 保留分隔符
    r = re.split(r"([12])", s)
    print(r)                            # ['a', '1', 'a', '2', 'a', '2', 'a', '1', '']
    
  • 替换
    import re
    
    s = "a1a2a2a1"
    
    # 使用匹配条件进行替换, 返回字符串
    # 可接收4个参数(匹配条件, 替换字符, 待匹配字符串, 替换次数), 匹配个数不填默认全部替换
    # 第三个参数还可以为
    	# re.S - 单行匹配
    	# re.M - 多行匹配
    	# re.I - 忽略大小写
    r = re.sub(r"\d", "-", s, 3)			
    print(r)								# a-a-a-a1, 本例中确定了替换次数为3, 所以只替换了前三个
    
    # 使用匹配条件进行替换, 返回tuple, (字符串, 替换次数)
    r = re.subn(r"\d", "-", s)
    print(r)								# ('a-a-a-a-', 4), 本例中替换了4次, 所以替换次数为4
    

高级用法

  • compile 编译(重复使用正则对象)
    import re
    
    s = "a1b1c1a2b2c2"
    
    # compile, 正则表达式编译成对象使用
    reobj = re.compile(r"\d")
    r = reobj.search(s)
    if r:
        print(r.group())
    
  • 正则分组命名
    import re
    
    s = "192.168.248.80:999"
    
    # 嵌套分组 + 分组命名 + group("命名")
    r = re.search(r"(?P<ip>(\d{1,3}\.){3}\d+):\d{1,3}", s)
    print(r.group("ip"))					# 192.168.248.80
    
  • group(), 配合正则分组或正则分组命名使用
    # 返回字符串, 可使用数字或字符串作为参数
    
    # 数字
    # 	group(0) 与 group()返回结果相同, 均为待匹配字符串
    #   group(1) 及以后, 为分组个数对应的序号, 超过个数会报错
    #   顺序为 先由外至内, 再由左到右
    
    s = "a 1 22 33 44"
    r = re.search(r"a (\d+) ((\d){2} (\d+)) (\d+)", s)
    print(r.group())        # a 1 22 32, 待匹配字符串
    print(r.group(0))       # a 1 22 32, 待匹配字符串
    print(r.group(1))       # 最外层, 第一个分组, 对应 1
    print(r.group(2))       # 最外层, 第二个分组, 对应 22
    print(r.group(3))       # 由于 22 内部包含分组, 先由外到内, 第三个分组对应 2
    print(r.group(4))       # 本层由左到右, 第四个分组对应 33
    print(r.group(5))       # 本层无分组, 回到上一层, 第五个分组对应 44
    
    # 字符串
    #   配合正则分组命名使用
    
    s = "a 1 22 33"
    r = re.search(r"a (?P<num1>\d+) (\d+) (?P<num3>\d+)", s)
    print(r.group("num1", "num3"))    # ('1', '33')
    
  • groups(), 配合正则分组使用
    # 可视为将 group() 所有结果放入 tuple 中返回, 顺序仍然为先由外到内, 再由左到右
    
    s = "a 1 22 33"
    r = re.search(r"a (((\d+) (\d+)) (\d+))", s)
    print(r.groups())  				# ('1 22 33', '1 22', '1', '22', '33')
    

hashlib - 加密模块

普通加密

import hashlib

# MD5 32位16进制
md5obj = hashlib.md5()
md5obj.update(password.encode('utf-8'))
ret = md5obj.hexdigest()

print('MD5pwd:',ret)


# sha1 40位16进制
sha1obj = hashlib.sha1()
sha1obj .update(password.encode('utf-8'))
ret = sha1obj .hexdigest()

print('SHA1pwd:',ret)

加盐加密

import hashlib

""" 使用固定字符串作为盐, 对密码进行加密 """

md5obj = hashlib.md5(salt.encode('utf-8'))
md5obj.update(password.encode('utf-8'))
ret = md5obj.hexdigest()

print(ret)

动态加盐加密

import hashlib

""" 使用用户名作为盐, 对密码进行加密 """

md5obj = hashlib.md5(username.encode('utf-8'))
md5obj.update(password.encode('utf-8'))
ret = md5obj.hexdigest()

print(ret)


requests - 请求

爬虫博客中有介绍


logging - 日志

示例

import logging

# 详细用法 - 3 个角色
# 1. Logger: 产生日志
l1 = logging.getLogger("server1")
# l2 = logging.getLogger("server2")

# 2. Handler: 接收 Logger 传过来的日志, 进行日志格式化和标准输出
sh1 = logging.StreamHandler() # 打印到终端
fh1 = logging.FileHandler("server1.log", encoding="utf-8") # 打印到文件
# h3 = logging.FileHandler("server2.log", encoding="utf-8")

# 3. Formatter: 日志格式 
f1 = logging.Formatter(
    fmt="%(asctime)s: %(message)s",
    datefmt="%Y-%m-%d %H:%M",
) # 终端输出格式

f2 = logging.Formatter(
    fmt="%(asctime)s - %(name)s - %(pathname)s - %(levelname)s - %(lineno)d: %(message)s",
    datefmt="%Y-%m-%d %H:%M",
) # 文件输出格式

# 5. 为 handler 绑定 formatter
sh1.setFormatter(f1)
fh1.setFormatter(f2)

# 6. 为 logger 绑定 handler
l1.addHandler(sh1) 
l1.addHandler(fh1)

# 7. 设置日志级别, logger 和 handler 都可以设置, logger<=handler
l1.setLevel(10)
sh1.setLevel(10)
fh1.setLevel(30)

# 8. 测试
l1.debug("1测试")
l1.info("1运行正常")
l1.warning("1要出问题了")
l1.error("1出 bug 了")
l1.critical("1完蛋")


format 参数中可能用到的格式化串

格式化串介绍
namelogger 的名字
levelno日志数字级别
levelname日志级别名称
pathname文件的绝对路径
filename文件名
module模块名
funcName方法名
lineno行号
asctime时间, 格式配合 datefmt 使用

collections

OrderedDict 有序字典

import collections

# 有序字典, 使用方法和普通字典完全一致

d = collections.OrderedDict()

d["a"] = 10
d["b"] = 20

print(d["a"])


defaultdict - value默认类型字典

from collections

d = collections.defaultdict(list)
print(d) # defaultdict(<class 'list'>, {})

# 因为type(v)为list, 所以v可以直接使用list的方法
d["a"].append(10)
print(d) # 结果为 defaultdict(<class 'list'>, {'a':[10]})

# 类型可以通过赋值直接转换
d["a"] = 10 # 此时 d["a"] 的类型为 int, 并且失去 list 的方法


namedtuple 可命名元组

import collections

# 坐标
Point = collections.namedtuple("Point", "x,y,z") # tuple 中 3 个元素, 三系坐标
print(Point) # <class '__main__.Point'>
 
p = Point(1,2,3)
print(p, p.x, p.y, p.z) # P(x=1, y=2, z=3) 1 2 3


# 纸牌
Card = namedtuple("Card", "suit, num") # tuple 中 2 个元素, 花色和数字

c = Card("梅花", "A")
print(c.suit, c.num) # 结果为 梅花 A


deque 双端队列

import collections

"""
    只能操作列表两端的数据
    为了避免操作list中, 非两端数据, 造成大量内存开销

"""

q = collections.deque()
print(q)

# append 从右侧加入
for i in range(3):
    q.append(i)
print(q) # deque([0, 1, 2])

# append 从左侧加入
for i in range(3):
    q.appendleft(i)
print(q) # deque([2, 1, 0, 0, 1, 2])

# pop 从右侧删除
q.pop()
print(q) # deque([2, 1, 0, 0, 1])

# popleft 从左侧删除
q.popleft()
print(q) # deque([1, 0, 0, 1])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值