【漫漫转码路】Python Day 22

一、json格式

用read和write的方式读取和写入文件,得到的文件内容都是字符串形式
如果想要使写入然后读取的文件的类型不发生变化,例如字典,保持键值对的映射关系,就需要用=用到其他的格式
python提供了json的标准模块
json是文本文件
json中所有键都要是双引号" "

1、步骤

python转换成json的过程步骤为:
python数据结构→json的字符串形式 (序列化)
json转换成python的过程为:
json→读取数据→python数据结构 (反序列化)

2、实现

利用json.loads和json.dumps可以实现序列化和反序列化
json.dumps():将数据序列化,并返回序列化的结果
json.loads():将数据序列化,并返回序列化的结果

# 例如
import json

dict1 = {"name": "Tom", "age": 18, 1: "one"}
with open("./test1.json", mode='w+') as file:
    json_dict1 = json.dumps(dict1)  # 将dict1序列化
    print(type(json_dict1))  
    print(json_dict1)  # 可以看到原来键为数字1,转换之后,键成了字符串1
    file.write(json_dict1)

with open("./test1.json", mode='r') as file:
    str_dict1 = file.read()  # 读取json内容
    print(type(str_dict1))  # 查看格式,是字符串
    new_dict1 = json.loads(str_dict1)  # 反序列化
    print(type(new_dict1))  # 查看反序列化之后的类型
    print(new_dict1)  # 输出
# 终端显示
<class 'str'>
{"name": "Tom", "age": 18, "1": "one"}
<class 'str'>
<class 'dict'>  # 可以发现,取出来之后,还是字典类型
{'name': 'Tom', 'age': 18, '1': 'one'}

利用load和dump可以简化
dump(data,file):将data序列化并写入file文件中
load(file):将file文件中的内容反序列化,并读取出来

# 例如
dict1 = {"name": "Tom", "age": 18, 1: "one"}
path = "./test1.json"
with open(path, mode='w+') as file:
    json.dump(dict1, file)  # 将dict1序列化并写入

with open("./test1.json", mode='r') as file:
    json.load(file)  # 反序列化并读取
# 终端显示
{'name': 'Tom', 'age': 18, '1': 'one'}

注意:
两个函数一个是dump一个是dumps
一个是load,一个是loads
注意区分

二、pickle格式

是二进制序列格式,不是文本文件,是二进制文件
过程同json一样,需要序列化,和反序列化
涉及的函数一样,dump,dumps,load,loads

三、xml格式

xmi格式是文本文件,
xml文档的第一句是声明语句,
声明语句后面的第一个元素是根元素,根元素有且只有一个
其他元素都是根元素的子元素,
并且每个xml元素包括一个开始标签,一个结束标签,连个标签中间的是内容
全程面向对象

ElementTree 是可迭代对象,支持序列协议,有__getitem__,可以被for循环,但是不能被isinstance判断

import xml.etree.ElementTree as ET  # 导入

.text可以获取内容(标签之间的东西)
.tag可以获取标签

四、正则表达式

正则表达式(Regular Expression)
正则表达式是给字符串立规矩的,制定规则来约束字符串;
python通过内置re模块实现
把字符串的每个元素和正则表达式的规则去匹配
正则表达式也是字符串
正则表达式分为普通字符和特殊字符
普通字符:大多数字符和字母
特殊字符(元字符):. ^ $ * + ? {} [] \ | ()

1、普通字符(部分)

(1)compile和search

compile(‘字符串’,flags= 0):字符串是准备制定规矩的字符串,flags是多种匹配方式(有很多种,每种方式又有不同的功能),编译后是一个pattern的实例对象

p.search(string[, pos[, endpos]]):扫描整个string,去寻找目标字符串,直到与第一个目标字符串匹配
返回一个实例对象,是Match类的实例对象,如果没有找到,返回None,pos是起始位置,默认为1;endpos是结束位置,默认到最后

Match实例对象支持很多对象方法:
m.span():索引,返回要检索的字符串在目标字符串中的第一个的开始索引和结束索引,前闭后开
m.start():开始位置索引
m.end()结束位置索引
m.group():要检索的内容

# 例如
import re

string = 'abcdefg'
p = re.compile('abc')  # 编译正则表达式,返回一个Pattern的实例对象,Pattern是一个类
m = p.search(string)  # 然后用p调用对象方法,返回一个Match类的实例对象
m1 = p.search(string, 1, -1)  # 指定起始和结束位置
print(m)
print(m.span())
print(m.start())
print(m.end())
print(m.group())
print(m1)
# 终端显示
<re.Match object; span=(0, 3), match='abc'>  # 可以看到,m也是一个实例对象,但是仔细看可以发现要检索的内容和索引欸
(0, 3)
0
3
abc
None  # 指定完位置之后发现结果变成了空,就是没有检索到

(2)match

p.match(string[, pos[, endpos]]):如果字符串的起始位置匹配成功,返回起始位置,如果没有,则返回None

# 例如
import re

string = 'abcdefg'
p = re.compile('abc')  # 编译正则表达式,返回一个pattern的实例对象,pattern是一个类
m = p.match(string)
m1 = p.match(string, 1, -1)  # 指定起始位置之后,abc与string不匹配
print(m)
print(m.span())
print(m1)
 # 终端显示
 <re.Match object; span=(0, 3), match='abc'>
(0, 3)
None

(3)fullmatch

p.fullmatch(string[, pos[, endpos]]):这个要求更为严格,要求检索内容和被检索目标完全匹配,也就是一样

# 例如
import re

string = 'abcdefg'
string1 = 'abc'
p = re.compile('abc')  # 编译正则表达式,返回一个pattern的实例对象,pattern是一个类
m = p.fullmatch(string)
m1 = p.fullmatch(string1)
m2 = p.fullmatch(string1, 1, -1)
print(m)
print(m1)
print(m2)
# 终端显示
None  # abc和abcdefg不是全匹配
<re.Match object; span=(0, 3), match='abc'>  # abc和abc是可以的
None  # 指定起始位置和结束位置之后不行了

(4)findall

p.findall(string[, pos[, endpos]]):将所有匹配的string找出来,并返回一个列表

# 例如
import re

string = 'abcdefbcgbc'
string1 = 'abc'
p = re.compile('bc')  # 编译正则表达式,返回一个pattern的实例对象,pattern是一个类
m = p.findall(string)
m1 = p.findall(string1)
m2 = p.findall(string1, 1, -1)
print(m)
print(m1)
print(m2)
# 终端显示
['bc', 'bc', 'bc']  # 注意啊,这个家伙返回的是一个列表
['bc']
[]

(5)finditer

p.findaiter(string[, pos[, endpos]]):具体功效和findally一样,就是返回了一个迭代器

# 例如
import re

string = 'abcdefbcgbc'
string1 = 'abc'
p = re.compile('bc')  # 编译正则表达式,返回一个pattern的实例对象,pattern是一个类
m = p.finditer(string)
m1 = p.finditer(string1)
m2 = p.finditer(string1, 1, -1)
print(m)
print([i.group() for i in list(m)])  # 用列表推导式可以提取出来数据
print(m1)
print(list(map(lambda x: x.group(), m1)))  # 用map也行
print(m2)
# 终端显示
<callable_iterator object at 0x00000117C2714640>  # 是个迭代器啊啊啊啊啊啊啊
['bc', 'bc', 'bc']
<callable_iterator object at 0x00000117C2876FA0>
['bc']
<callable_iterator object at 0x00000117C265FFA0>

2、特殊字符(部分)

(1).(点)

.:点,匹配除了换行符以外的任意一个字符
意思就是正常状态下啥都能当

# 例如
import re
str1 = '\\'  # 注意注意,这里'\\'表示一个反斜杠,因为如果写成'\',其中的\'会被认为是转义,所以要对\'进行转义,就成了'\\'
p = re.compile('\\\\')  # 然后在这里又要进行一次转义,每个\需要一个\来转义,就变成了'\\\\'
m = p.findall(str1)
print(m)
p1 = re.compile(r'\\')  # 或者可以用r抑制转义
m = p.findall(str1)
print(m)
# 终端显示
['\\']
['\\']

所以,正则表达式在编译的时候都会加r,原始字符串,抑制转义

# 例如
import re

string = 'abcdeahhhh\nbchhhhfbcgbc'
string1 = 'abc'
p = re.compile('.bc')  
m = p.findall(string)
print(m)
p1 = re.compile('.bc',flags = re.S)    # re.S模式下
m1 = p1.findall(string)
print(m1)
# 终端显示
['abc', 'fbc', 'gbc']
['abc', '\nbc', 'fbc', 'gbc'] # 看到没,re.S模式下这个.可以匹配换行符啊啊啊啊啊,神奇吧

(2)^

用来匹配字符串的开头
只能用来匹配开头,限定范围pos和endpos是没有用的!

# 例如
import re

string = 'abcdeahhhh\nbchhhhfbcgbc'
string1 = 'bcdefhg'
p = re.compile(r'^bc')
m = p.findall(string)
m1 = p.findall(string, 1)
m2 = p.findall(string1)
print(m)
print(m1)
print(m2)
# 终端显示
[]  # abcdeahhhh\nbchhhhfbcgbc不是以bc开头,所以返回空,可以理解
[]  # 但是更改开始位置pos之后,还是空啊,看到了没,这货完全不按套路出牌,意思就是只要bc前面有东西就不行,完全不给人机会,哪怕是设置pos也不行
['bc']  # 必须是这种的,开头就是bc的,才可以啊

进阶版,当再MULTILINE模式下,也就是re.M模式下,会检索字符串的开头和每一行的开始

# 例如
import re

string = 'abcdeahhhh\nbchhhhfbcgbc'
string1 = 'bcdefhg'
p = re.compile(r'^bc', flags=re.M)
m = p.findall(string)  # match,search啥的都不管用
m1 = p.findall(string, 1)
m2 = p.findall(string1)
print(m)
print(m1)
print(m2)
# 终端显示
['bc']  # abcdeahhhh\nbchhhhfbcgbc换行符后面就是下一行,的开始,\n后面是有bc的,所以可以被匹配到
['bc']  
['bc']

(3)$

匹配结尾,用法可以参照^
用法:1、匹配结尾有没有指定字符串,2、匹配结尾换行符之前有没有指定的字符串
进阶只有,即re.M模式下,增加一项,3、中间换行符前面有没有指定字符串

# 例如
import re

string = 'abcdeahhbc\nbchhhhfbcgbc\n'
string1 = 'bcdefhbcg'
string2 = 'abcd\njjjjj\n\n'
p = re.compile(r'bc$')  # 这个东西得放在最后,不能放开头
p1 = re.compile(r'\n$')
m = p.findall(string)
m1 = p.findall(string, endpos=-2)  # 指定结束位置endpos
m2 = p1.findall(string2)
print(m)
print(m1)
print(m2)
# 终端显示
['bc']  # 末尾换行符之前有一个bc
[]  # 即使指定endpos也不行,这一点跟^一样,后面不能有东西
['\n', '\n']  # 首先结尾是\n,所以被捕获,然后结尾的\n之前也是\n,所以也被捕获

进阶版,

# 例如
import re

string = 'abcdeahhbc\nbchhhhfbcgbc\n'
string1 = 'abcdeahhbc\nbchhhhfbcgbcg\n'
string2 = 'abcd\njjjjj\n\n'
p = re.compile(r'bc$', flags=re.M)  # 改为re.M模式
p1 = re.compile(r'\n$', flags=re.M)
p2 = re.compile(r'\n$', flags=re.M)
m = p.findall(string)
m2 = p2.findall(string2)
m1 = p.findall(string1, endpos=-1)
m3 = p.findall(string1)
print(m)
print(m2)
print(m1)
print(m3)
# 终端显示
['bc', 'bc']  # 结尾\n前面一个bc,中间\n前面一个bc
['\n', '\n']  # 结尾一个\n,结尾\n前面一个\n,中间的\n前面没有\n,可以找到中间\n之前的东西,但是不包括\n,所以中间的\n不在此列
[]  #  ***注意***  当指定结尾-1之后,发现已经为空了,解释为,当要求结尾有结束字符串的时候,所有行都会按照这个算,abcdeahhbc\nbchhhhfbcgbcg\n中abcdeahhbc\n结尾到-1的话就是abcdeahhb,不符合要求
['bc']  # 注意和上面的作对比,abcdeahhbc\nbchhhhfbcgbcg\n,只有在中间的\n前面有一个bc

妖魔鬼怪

# 例如
import re

string = 'abcdef\n\nbcdefg\n\n'

p = re.compile(r'.$', re.M | re.S)  # |在这里表示或的意思,就是两个模式都会有
e = p.findall(string)
print(e)
# 终端显示
['f', '\n', 'g', '\n', '\n']
# 首先,re.M模式下表示多行,$就是三个位置,re.S表示.可以表示换行符
# 那么首先
# 第一个位置,结尾,是\n
# 第二个位置,结尾的前面,是\n
# 第三个位置,中间\n的前一个字符
# 中间有三个\n,f\n前面是f,\n\n前面是\n,g\n前面是g,
# 因此结果组合起来,按顺序排序就是
# ['f', '\n', 'g', '\n', '\n']

3、编译标志(部分)

就是compile(‘字符串’,flags= 0):里的flags的可选的参数,会对编译进行微调

re.I或re.IGNORECASE,忽略大小写匹配

re.S或re.DOTALL,使.匹配包括换行符在内的所有字符,如果没有设置的时候是不能匹配换行符的

re.M或re.MULTILINE,多行匹配,影响^和$,开启之后,^会匹配每一行的开始,$会匹配结尾以及每个换行符的前面

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值