python入门学习笔记——详细基础知识篇(第10章 正则表达式(重点)与JSON)

第10章 正则表达式(重点)与JSON

  • 初识正则表达式
  • 元字符与普通字符
  • 字符集
  • 概括字符集
  • 数量词
  • 贪婪与非贪婪
  • 匹配0次1次或者无限多次
  • 边界匹配符(^ 、$)
  • 匹配模式参数
  • re.sub正则替换
  • 把函数作为参数传递
  • search 与 match函数
  • group分组
  • 一些关于学习正则的建议
  • 理解JSON
  • 反序列
  • 序列化
  • 小谈JSON、JSON对象与JSON字符串(了解)

初识正则表达式

(1)正则表达式 是一个特殊的 字符序列,检测 一个字符串 是否与我们所设定的这样的字符序列相匹配。 (即字符串是否与正则表达式相匹配)

快速检索文本、实现一些替换文本的操作。

正则表达式是用来操作字符串的。

正则表达式的应用:

1.检查一串数字是否是电话号码
2.检测一个字符串是否符合email
3.把一个文本里指定的单词替换为另外一个单词

(2)简单的字符判断时,优先选择python的内置函数:

a = 'C|C++|Java|C#|Python|Javascript'

print(a.index('Python')>-1)

print('Python' in a)

输出:
True
True

(3)如何运用正则表达式:

Python中提供了一个 re模块:其中很多的方法可以用来操作正则表达式。

import re

a = 'C|C++|Java|C#|Python|Javascript'

r = re.findall('Python',a)    #匹配常量字符串 #调用了re模块的findall方法  
                             # r=re.findall('正则表达式',a)
print(r)

if len(r) > 0:
    print('字符串中包含Puython')


输出:
['Python']
字符串中包含Puython

元字符与普通字符

(1)上小节中举的例子匹配的常量字符串,没有真正发挥正则表达式的意义。

import re

a = 'C0C++7Java8C#9Python6Javascript'  #找数字

r = re.findall('\d',a)   # \d可以表示数字0-9
print(r)

输出:
['0', '7', '8', '9', '6']

(2)上一节例子中组成正则表达式的 python ————叫做普通字符
像这里例子中的 ‘ \d ’ 组成正则表达式 ———— ‘ \d ’ 叫做元字符

正则表达式就是由一系列的普通字符与元字符组合而成的。学习正则表达式主要是学习元字符,不要死记硬背,根据自己的需求,去元字符表中查询就可以了。

python入门学习笔记——详细基础知识篇(第10章 正则表达式(重点)与JSON)_第1张图片

字符集

字符集的特性

# 字符集
import re
s = 'abc, acc, adc, aec, afc, ahc'1)
r = re.findall('a[cf]c',s)     # []
print(r)
输出:['acc', 'afc']2)
r = re.findall('a[^cf]c',s)   # ^
print(r)
输出:['abc', 'adc', 'aec', 'ahc']3)
r = re.findall('a[c-f]c',s)   # -
print(r)
输出:['acc', 'adc', 'aec', 'afc']
    

概括字符集

(1)例如:“\d”也是概括字符集的一种 :代表数字0-9。

(2)
\w —————— 既能匹配数字又能匹配字母,它匹配的范围:[A-Za-z0-9_]
(即大写字母A到Z,小写字母a到z,数字0到9,还可以匹配下划线)(只能匹配单词字符)(只能匹配一个字符)

\W ———— 大写匹配非单词字符

import re
a = 'python1111java&__678php'  

r = re.findall('\w',a)    #不能匹配到&这种非单词字符
print(r)

输出:
['p', 'y', 't', 'h', 'o', 'n', '1', '1', '1', '1', 'j', 'a', 'v', 'a', '_', '_', '6', '7', '8', 'p', 'h', 'p']
import re
a = 'python1111java&__678php'

r = re.findall('\W',a)  #大写匹配非单词字符
print(r)

输出:['&']

常见的非单词字符:\n , \r , \t,‘ ’

(3)
\s ———— 匹配空白字符
\S ———— 匹配非空白字符

import re
a = 'python11 \t11java&\n678\rphp'

r = re.findall('\s',a)
print(r) 

输出:
[' ', '\t', '\n', '\r']

数量词

(1)[a-z]

import re
a = 'python 1111java678php'

r = re.findall('[a-z]',a)
print(r) 

输出:
['p', 'y', 't', 'h', 'o', 'n', 'v', 'j', 'a', 'v', 'a', 'p', 'h', 'p']

(2)数量词的用法: {数字1,数字2}

import re
a = 'python 1111java678php'

r = re.findall('[a-z]{3,6}',a)
print(r) 

输出:['python', 'java', 'php']

贪婪与非贪婪

(1)

默认情况下是贪婪的匹配方式:如果把数量词限定在一个区间内,会尽可能多的取最大的一个区间内的值。

例如:上小节的例子中[a-z]{3,6}匹配区间是3到6,匹配到‘pyt’时,并不会认为成立,它会匹配更多(贪婪的),直到匹配完‘python’。

(2)非贪婪(如何表示:在区间后加上问号)

import re
a = 'python 1111java678php'
r = re.findall('[a-z]{3,6}?',a)
print(r) 

输出:
['pyt', 'hon', 'jav', 'php']

注:在这个例子中 界限 取3是非贪婪,取6是贪婪

匹配0次1次或者无限多次

(1)*

 * : 表示匹配 *前面的字符 0次或无限多次
 
import re
a = 'pytho0python1pythonn2'

r = re.findall('python*',a)
print(r) 

输出:['pytho', 'python', 'pythonn']:第一个'pytho'缺少一个n,符合匹配0次
python,匹配一次
pythonn,匹配2

(2)+

+ : 匹配1次或者无限多次

把 * 换成 + 会输出:['python', 'pythonn']

(3)?

?: 匹配0次或1次

输出:['pytho', 'python', 'python']   

注:多出来的n会被去掉。可以用? 做去重操作。
如果问号前有数量词的话就从数量词中选交小的数作为匹配次数

(4)

import re
a = 'pytho0python1pythonn2'

r = re.findall('python{1,2}',a)   #匹配一次或两次
print(r) 
输出:['python', 'pythonn']

r = re.findall('python{1,2}?',a)  # ?:非贪婪:匹配一次
输出:['python', 'python']

r = re.findall('python?',a)  # ?:匹配0次或一次
输出:['pytho', 'python', 'python']

边界匹配符(^ 、$)

import re
a = '1000019090890'
# 验证位数是否为4-8位
r = re.findall('\d{4,8}',a)
print(r) 

输出:['10000190', '90890']

r = re.findall('^\d{4,8}$',a)
输出:[]

^ : 表示从字符串的开始进行匹配
$ : 表示从字符串的末尾开始匹配
两个一前一后:匹配完整的字符

import re
a = '100000001'

r = re.findall('000',a)
print(r) 
输出:['000', '000']

r = re.findall('^000',a) —————————— 表示的匹配条件: 字符串开始三个数字是000
输出:[]     

r = re.findall('000$',a) —————————— 表示的匹配条件:字符串最后三个数字是000
输出:[]

import re
a = 'PythonPythonPythonPythonPython'    # 判断该字符串里是否包含三个Python
r = re.findall('(Python){3}(JS)',a)     # 用‘PythonPythonPython’作为表达式当然可以,但不简洁
print(r) 

# 括起来的一系列字符就叫组 加上数量词,就表示把一组的字符重复若干次
# 可以有多个组,例如后面可以加一个(JS),这也是一个组

中括号里面是或关系,小括号里面是且关系。[abc] :表示匹配a或b或c;(Python) :表示每个字符都出现。

匹配模式参数

作用:忽略大小写的差异

import re
a = 'PythonC#JavaPHP'
r = re.findall('c#',a,re.I)  
print(r) 

输出:['C#']

多个模式之间用竖线隔开
. 表示匹配除换行符\n之外其他所有字符
import re
a = 'PythonC#\nJavaPHP'
r = re.findall('c#.{1}',a,re.I | re.S)   # re.S:让 " . " 匹配所有字符包括\n
print(r)
输出:['C#\n']

r = re.findall('c#.{1}',a,re.I)  # 如果不加re.S则 “.” 不会匹配 \n
输出:[]

re.sub正则替换

(1)用re模块中的sub函数来实现替换:re.sub

import re
a = 'PythonC#JavaC#PHP'

r = re.sub('C#','Go',a,0)  # 参数为0时把所有C#替换成Go
print(r)
输出:PythonGoJavaGoPHP   

r = re.sub('C#','Go',a,1) # 参数为1时只有第一个匹配到的C#替换成了Go
print(r)
输出:PythonGoJavaC#PHP

(2)一些简单的替换可以用 内置函数 replace:

import re
a = 'PythonC#JavaC#PHP'
a.replace('C#','Go')
print(a)

输出:PythonC#JavaC#PHP
这里并没有被替换掉,是因为字符串不可变,要改变的话就要新生成一个变量来接收。代码如下:

import re
a = 'PythonC#JavaC#PHP'
r = a.replace('C#','Go')
print(r)
输出:PythonGoJavaGoPHP

(3)

import re
a = 'PythonC#JavaC#PHP'

def convert(value):
    pass

r = re.sub('C#',convert,a)
print(r)

输出:PythonJavaPHP

如果我们把 一个函数 作为 sub函数 的第二个参数:当正则表达式匹配到结果时,会把匹配到的结果传到该函数。

这里convert 函数中的value即正则表达式匹配到的结果‘C#’, 这里convert函数的返回结果会替换‘C#’

返回的并不只是一个简单的字符串'C#',而是一个对象

import re
a = 'PythonC#JavaC#PHP'

def convert(value):
    print(value)
    # return '!!'+value+'!!'

r = re.sub('C#',convert,a)
print(r)

输出:
<re.Match object; span=(6, 8), match='C#'>    # 这里的span是匹配到的位置,是第7、8位
<re.Match object; span=(12, 14), match='C#'>  # 第二次匹配到的位置时13、14位
PythonJavaPHP
不能对返回的对象直接操作,所以用group方法获取匹配到的字符串

import re
a = 'PythonC#JavaC#PHP'

def convert(value):
    matched = value.group()   
    return '!!'+ matched +'!!'

r = re.sub('C#',convert,a)
print(r)

输出:Python!!C#!!Java!!C#!!PHP

把函数作为参数传递

import re
a = 'A8C3434D378'    
#实现把大于等于6的替换成9,否则替换为0
def convert(value):
    matched = value.group()
    if matched  >=6:     
        return 9
    else:
        return 0
r = re.sub('\d',convert,a)
print(r)

这里运行会报错:报错 一是因为现在数字是以字符串的形式出现的,要先类型转换一下。二是 也不能直接把整型数字返回,因为是用正则表达式,它只能操作字符串。

更改代码如下:  

def convert(value):
    matched = value.group()
    if int(matched)  >=6:     
        return '9'
    else:
        return '0'

输出:A9C0000D099

从这个例子可以理解把函数作为参数接收的重要意义:实现把一些复杂的逻辑赋予参数。自己在平常编写代码时可以多试试如何运用这样的形式。多思考。

search 与 match函数

(1)
match函数特征:从字符串 首字符 开始进行匹配,如果没有匹配成功,则返回None。第一个匹配成功则马上返回结果。

search函数特征:搜索字符串,一般找到结果之后,就马上返回结果。

(2)例子

import re
s='A8C3434D378'   

r= re.match('\d',s)   #从字符串开始就要匹配,这里开头不是数字,所以返回None
print(r)
r1 = re.search('\d',s) 
print(r1)

输出:
None       
<re.Match object; span=(1, 2), match='8'>
import re
s='88C3434D378'   
r= re.match('\d',s)   
print(r)
r1 = re.search('\d',s) 
print(r1.group())

输出:
<re.Match object; span=(0, 1), match='8'>
8

(3)span() 方法 是返回正则匹配结果在原字符串的位置

import re
s='88C3434D378'   

r= re.match('\d',s)   
print(r.span())

输出:(0, 1)

(4)search 与 match 函数与findall函数区别:
group 与 match 函数:如果匹配成功,将立刻返回当前匹配到的结果,不会继续往前搜索。
findall 函数:会把所有匹配结果都打印出来

group分组

(1)问题引入:提取life和python之间的字符

代码1import re
s='life is short,i use python'    

r= re.match('life.*python',s)   
print(r.group())

输出:life is short,i use python

(2)探索:

group 实际上获取的是一个分组匹配的值

代码二:
import re
s='life is short,i use python'   
# 提取life和python之间的字符
r= re.match('(life.*python)',s)  
print(r.group(0))  

输出:life is short,i use python

结果与代码一的结果一样:因为正则表达式默认是一个分组
group函数可以传入参数,代表组号,这里只有一个组,参数传0或者不写都可以。
group(0)比较特殊,记录的永远是正则表达式的完整匹配的结果。
代码三:
若想访问完整匹配的内部的结果:应该改为:
r= re.match('life(.*)python',s)      
print(r.group(1))  

输出结果: is short,i use

上面的例子用search函数也是一样的。

(3)用findall 函数

import re
s='life is short,i use python'   
# 提取life和python之间的字符
r= re.findall('life(.*)python',s)   
print(r)   

输出:[' is short,i use ']

推荐findall函数,更简洁快速。

(4)关于group

import re
s='life is short,i use python, i love python'   
# 提取life和python之间的字符
r= re.search('life(.*)python(.*)python',s)  # 出现了两个分组
print(r.group(0,1,2)) 

输出:
('life is short,i use python, i love python', ' is short,i use ', ', i love ')
import re
s='life is short,i use python, i love python'   
# 提取life和python之间的字符
r= re.search('life(.*)python(.*)python',s)  
print(r.groups())      

groups不会返回完整的匹配结果

输出:(' is short,i use ', ', i love ')

一些关于学习正则的建议

(1)善于运用正则表达式 解决字符串相关的问题
(2)对于电话号码的判断、qq号的判断、邮箱的判断等非常常见的校验规则,可以用别人已经写好的,不必要自己去编写,从而提高工作效率。
(3)从学习角度:还是可以分析一下别人的正则表达式是怎么写的,平时有意识的使用正则表达式。

理解JSON

(1)什么是JSON:

是一种轻量级的数据 交换格式JSON是一种数据格式。字符串是JSON的表现形式。

符合JSON格式的字符串叫做JSON字符串。

(2)JSON优势:易阅读,易解析,网络传输效率高,适合跨语言交换数据
python入门学习笔记——详细基础知识篇(第10章 正则表达式(重点)与JSON)_第2张图片

python入门学习笔记——详细基础知识篇(第10章 正则表达式(重点)与JSON)_第3张图片

总结:
1.JSON是为了做数据交换而定制的一个规则和规范。JSON的载体:JSON字符串。
2.JSON是跨语言的。

反序列

(1)JSON数据类型 如何转换到 Python数据类型?

import json
json_str = '{"name":"qiyue","age":18}'  

#在JSON字符串中,除了数字类型其他都要加引号,且规定只能是双引号(JSON规定),那么外层就只能是单引号了(Python规定)。
#这里的{"name":"qiyue","age":18}就是符合JSON规范的JSON字符串了,这里的JSON也可以看做是object(对象)

student = json.loads(json_str)
print(type(student))
print(student)

输出:
<class 'dict'>
{'name': 'qiyue', 'age': 18}

# 说明通过load函数已经把把JSON字符串转化为了字典,下面打印出的是一个字典

print(student['name'])
print(student['age'])
输出:
qiyue
18

(2)对于同样的JSON字符串,不同的语言可能会把它变成不同的数据类型。在Python中转换成字典,在其他语言是不一定的。

(3)如果JSON是一个数组的话,JSON字符串怎么表示。

import json
json_str = '[{"name":"qiyue","age":18},{"name":"qiyue","age":18}]'

student = json.loads(json_str)
print(type(student))
print(student)

输出:
<class 'list'>
[{'name': 'qiyue', 'age': 18}, {'name': 'qiyue', 'age': 18}]
import json
json_str = '[{"name":"qiyue","age":18,"flag":false},{"name":"qiyue","age":18}]'
#false不是字符串,不用加引号
student = json.loads(json_str)
print(type(student))
print(student)

输出:
<class 'list'>
[{'name': 'qiyue', 'age': 18, 'flag': False}, {'name': 'qiyue', 'age': 18}]  
#把JSON中的小写false变成了大写,因为在Python中是大写的。

这里示例是想说明 :JSON是有自己的数据类型的,我们用 loads 函数是为了 把JSON的数据类型转换为Python的数据类型。

(4)反序列化的定义(了解):由字符串到语言下的某一种数据结构的这一过程 叫做反序列化。

序列化

(1)JSON与Python之间的类型对照表。
python入门学习笔记——详细基础知识篇(第10章 正则表达式(重点)与JSON)_第4张图片

(2) Python数据类型向JSON字符串转换的一个过程——————叫做序列化

import json
student = [
            {'name':'qiyue','age':18,'flag':False},
            {'name':'qiyue','age':18}
          ]
json_str = json.dumps(student)     #字典也是对象
print(type(json_str))
print(json_str)

输出:
<class 'str'>
[{"name": "qiyue", "age": 18, "flag": false}, {"name": "qiyue", "age": 18}]  

扩展:不只是python与JSON之间的转换才叫 序列化 或 反序列化。

(3)序列化的意义:通过调用服务得到JSON字符串,然后转换为Python的数据结构,从而获取到JSON字符串里面的相关信息。

小谈JSON、JSON对象与JSON字符串(了解)

(1)

JSON (JavaScript Object Notation) :仅仅是一种数据格式,可以跨平台数据传输,速度快。

JavaScript :是一个标准的实现方案之一,服务器的一种语言。是一个类的实例。不能传输。

Json字符串:符合JSON格式的字符串叫做JSON字符串。(所谓字符串:单引号或者双引号引起来 )

Json对象: 最显著的特征:对象的值可以用 “对象.属性” 进行访问

(2)python入门学习笔记——详细基础知识篇(第10章 正则表达式(重点)与JSON)_第5张图片python入门学习笔记——详细基础知识篇(第10章 正则表达式(重点)与JSON)_第6张图片

你可能感兴趣的:(#,python入门课程学习笔记,python,正则表达式)