正则表达式
常用单词
- copy 英 ['kɒpɪ] 复制;复印;
- deepcopy 深拷贝
- append 英 [ə'pend] 追加,附加;
- reload 英 [riː'ləʊd] 重新装,重新加载
- module 英 ['mɒdjuːl] 模块;组件;
with语句
1. with语句的使用
基础班向文件中写入数据的示例代码:
# 1、以写的方式打开文件
f = open("1.txt", "w")
# 2、写入文件内容
f.write("hello world")
# 3、关闭文件
f.close()
Copy
代码说明:
- 文件使用完后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的
这种写法可能出现一定的安全隐患,错误代码如下:
# 1、以读的方式打开文件
f = open("1.txt", "r")
# 2、读取文件内容
f.write("hello world")
# 3、关闭文件
f.close()
Copy
运行结果:
Traceback (most recent call last):
File "/home/python/Desktop/test/xxf.py", line 4, in <module>
f.write("hello world")
io.UnsupportedOperation: not writable
Copy
代码说明:
- 由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。
- 为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来解决
安全写法, 代码如下:
try:
# 1、以读的方式打开文件
f = open("1.txt", "r")
# 2、读取文件内容
f.write("xxxxx")
except IOError as e:
print("文件操作出错", e)
finally:
# 3、关闭文件
f.close()
Copy
运行结果:
文件操作出错 not writable
Copy
这种方法虽然代码运行良好,但是缺点就是代码过于冗长,并且需要添加try-except-finally语句,不是很方便,也容易忘记.
在这种情况下,Python提供了 with 语句的这种写法,既简单又安全,并且 with 语句执行完成以后自动调用关闭文件操作,即使出现异常也会自动调用关闭文件操作。
with 语句的示例代码:
# 1、以写的方式打开文件
with open("1.txt", "w") as f:
# 2、读取文件内容
f.write("hello world")
Copy
2. 小结
- Python 提供了 with 语句用于简化资源释放的操作
深拷贝和浅拷贝
1. 浅拷贝
copy函数是浅拷贝,只对可变类型的第一层对象进行拷贝,对拷贝的对象开辟新的内存空间进行存储,不会拷贝对象内部的子对象。
不可变类型的浅拷贝示例代码:
import copy # 使用浅拷贝需要导入copy模块
# 不可变类型有: 数字、字符串、元组
a1 = 123123
b1 = copy.copy(a1) # 使用copy模块里的copy()函数就是浅拷贝了
# 查看内存地址
print(id(a1))
print(id(b1))
print("-" * 10)
a2 = "abc"
b2 = copy.copy(a2)
# 查看内存地址
print(id(a2))
print(id(b2))
print("-" * 10)
a3 = (1, 2, ["hello", "world"])
b3 = copy.copy(a3)
# 查看内存地址
print(id(a3))
print(id(b3))
Copy
运行结果:
140459558944048
140459558944048
----------
140459558648776
140459558648776
----------
140459558073328
140459558073328
Copy
不可变类型的浅拷贝说明:
- 通过上面的执行结果可以得知,不可变类型进行浅拷贝不会给拷贝的对象开辟新的内存空间,而只是拷贝了这个对象的引用。
可变类型的浅拷贝示例代码:
import copy # 使用浅拷贝需要导入copy模块
# 可变类型有: 列表、字典、集合
a1 = [1, 2]
b1 = copy.copy(a1) # 使用copy模块里的copy()函数就是浅拷贝了
# 查看内存地址
print(id(a1))
print(id(b1))
print("-" * 10)
a2 = {"name": "张三", "age": 20}
b2 = copy.copy(a2)
# 查看内存地址
print(id(a2))
print(id(b2))
print("-" * 10)
a3 = {1, 2, "王五"}
b3 = copy.copy(a3)
# 查看内存地址
print(id(a3))
print(id(b3))
print("-" * 10)
a4 = [1, 2, [4, 5]]
# 注意:浅拷贝只会拷贝父对象,不会对子对象进行拷贝
b4 = copy.copy(a4) # 使用copy模块里的copy()函数就是浅拷贝了
# 查看内存地址
print(id(a4))
print(id(b4))
print("-" * 10)
# 查看内存地址
print(id(a4[2]))
print(id(b4[2]))
# 修改数据
a4[2][0] = 6
# 子对象的数据会受影响
print(a4)
print(b4)
Copy
运行结果:
139882899585608
139882899585800
----------
139882919626432
139882919626504
----------
139882919321672
139882899616264
----------
139882899587016
139882899586952
----------
139882899693640
139882899693640
[1, 2, [6, 5]]
[1, 2, [6, 5]]
Copy
可变类型的浅拷贝说明:
- 通过上面的执行结果可以得知,可变类型进行浅拷贝只对可变类型的第一层对象进行拷贝,对拷贝的对象会开辟新的内存空间进行存储,子对象不进行拷贝。
2. 深拷贝
deepcopy函数是深拷贝, 只要发现对象有可变类型就会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储。
不可变类型的深拷贝示例代码:
import copy # 使用深拷贝需要导入copy模块
# 不可变类型有: 数字、字符串、元组
a1 = 1
b1 = copy.deepcopy(a1) # 使用copy模块里的deepcopy()函数就是深拷贝了
# 查看内存地址
print(id(a1))
print(id(b1))
print("-" * 10)
a2 = "张三"
b2 = copy.deepcopy(a2)
# 查看内存地址
print(id(a2))
print(id(b2))
print("-" * 10)
a3 = (1, 2)
b3 = copy.deepcopy(a3)
# 查看内存地址
print(id(a3))
print(id(b3))
print("-" * 10)
# 注意: 元组里面要是有可变类型对象,发现对象有可变类型就会该对象到最后一个可变类型的每一层对象进行拷贝
a4 = (1, ["李四"])
b4 = copy.deepcopy(a4)
# 查看内存地址
print(id(a4))
print(id(b4))
# 元组里面的可变类型子对象也会进行拷贝
print(id(a4[1]))
print(id(b4[1]))
Copy
运行结果:
9289120
9289120
----------
140115621848320
140115621848320
----------
140115621859592
140115621859592
----------
140115602480584
140115621834568
140115602328136
140115602436168
Copy
不可变类型的深拷贝说明:
- 通过上面的执行结果可以得知:
- 不可变类型进行深拷贝如果子对象没有可变类型则不会进行拷贝,而只是拷贝了这个对象的引用,否则会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储
可变类型的深拷贝示例代码:
import copy # 使用深拷贝需要导入copy模块
# 可变类型有: 列表、字典、集合
a1 = [1, 2]
b1 = copy.deepcopy(a1) # 使用copy模块里的deepcopy()函数就是深拷贝了
# 查看内存地址
print(id(a1))
print(id(b1))
print("-" * 10)
a2 = {"name": "张三"}
b2 = copy.deepcopy(a2)
# 查看内存地址
print(id(a2))
print(id(b2))
print("-" * 10)
a3 = {1, 2}
b3 = copy.deepcopy(a3)
# 查看内存地址
print(id(a3))
print(id(b3))
print("-" * 10)
a4 = [1, 2, ["李四", "王五"]]
b4 = copy.deepcopy(a4) # 使用copy模块里的deepcopy()函数就是深拷贝了
# 查看内存地址
print(id(a4))
print(id(b4))
# 查看内存地址
print(id(a4[2]))
print(id(b4[2]))
a4[2][0] = "王五"
# 因为列表的内存地址不同,所以数据不会收到影响
print(a4)
print(b4)
Copy
运行结果:
140348291721736
140348291721928
----------
140348311762624
140348311221592
----------
140348311457864
140348291752456
----------
140348291723080
140348291723144
140348291723208
140348291723016
[1, 2, ['王五', '王五']]
[1, 2, ['李四', '王五']]
Copy
可变类型的深拷贝说明:
- 通过上面的执行结果可以得知, 可变类型进行深拷贝会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储。
3. 浅拷贝和深拷贝的区别
- 浅拷贝最多拷贝对象的一层
- 深拷贝可能拷贝对象的多层
4. 总结
- 浅拷贝使用copy.copy函数
- 深拷贝使用copy.deepcopy函数
- 不管是给对象进行深拷贝还是浅拷贝,只要拷贝成功就会开辟新的内存空间存储拷贝的对象。
- 浅拷贝和深拷贝的区别是:
- 浅拷贝最多拷贝对象的一层,深拷贝可能拷贝对象的多层。
正则表达式的概述
1. 正则表达式的介绍
在实际开发过程中经常会有查找符合某些复杂规则的字符串的需要,比如:邮箱、图片地址、手机号码等,这时候想匹配或者查找符合某些规则的字符串就可以使用正则表达式了。
2. 正则表达式概念
正则表达式就是记录文本规则的代码
3. 正则表达式的样子
0\d{2}-\d{8} 这个就是一个正则表达式,表达的意思是匹配的是座机号码
4. 正则表达式的特点
- 正则表达式的语法很令人头疼,可读性差
- 正则表达式通用行很强,能够适用于很多编程语言
5. 小结
- 正则表达式是匹配符合某些规则的字符串数据
re模块介绍
1. re模块的介绍
在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用一个 re 模块
# 导入re模块
import re
# 使用match方法进行匹配操作
result = re.match(正则表达式,要匹配的字符串)
# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()
Copy
2. re模块的使用
import re
# 使用match方法进行匹配操作
result = re.match("itcast","itcast.cn")
# 获取匹配结果
info = result.group()
print(info)
Copy
运行结果:
itcast
Copy
3. 小结
- re.match() 根据正则表达式从头开始匹配字符串数据
匹配单个字符
1. 匹配单个字符
在上一小节中,了解到通过re模块能够完成使用正则表达式来匹配字符串
本小节,将要讲解正则表达式的单字符匹配
代码 | 功能 |
---|---|
. | 匹配任意1个字符(除了\n) |
[ ] | 匹配[ ]中列举的字符 |
\d | 匹配数字,即0-9 |
\D | 匹配非数字,即不是数字 |
\s | 匹配空白,即 空格,tab键 |
\S | 匹配非空白 |
\w | 匹配非特殊字符,即a-z、A-Z、0-9、_、汉字 |
\W | 匹配特殊字符,即非字母、非数字、非汉字 |
示例1: .
import re
ret = re.match(".","M")
print(ret.group())
ret = re.match("t.o","too")
print(ret.group())
ret = re.match("t.o","two")
print(ret.group())
Copy
运行结果:
M
too
two
Copy
示例2:[]
import re
# 如果hello的首字符小写,那么正则表达式需要小写的h
ret = re.match("h","hello Python")
print(ret.group())
# 如果hello的首字符大写,那么正则表达式需要大写的H
ret = re.match("H","Hello Python")
print(ret.group())
# 大小写h都可以的情况
ret = re.match("[hH]","hello Python")
print(ret.group())
ret = re.match("[hH]","Hello Python")
print(ret.group())
ret = re.match("[hH]ello Python","Hello Python")
print(ret.group())
# 匹配0到9第一种写法
ret = re.match("[0123456789]Hello Python","7Hello Python")
print(ret.group())
# 匹配0到9第二种写法
ret = re.match("[0-9]Hello Python","7Hello Python")
print(ret.group())
ret = re.match("[0-35-9]Hello Python","7Hello Python")
print(ret.group())
# 下面这个正则不能够匹配到数字4,因此ret为None
ret = re.match("[0-35-9]Hello Python","4Hello Python")
# print(ret.group())
Copy
运行结果:
h
H
h
H
Hello Python
7Hello Python
7Hello Python
7Hello Python
Copy
示例3:\d
import re
# 普通的匹配方式
ret = re.match("嫦娥1号","嫦娥1号发射成功")
print(ret.group())
ret = re.match("嫦娥2号","嫦娥2号发射成功")
print(ret.group())
ret = re.match("嫦娥3号","嫦娥3号发射成功")
print(ret.group())
# 使用\d进行匹配
ret = re.match("嫦娥\d号","嫦娥1号发射成功")
print(ret.group())
ret = re.match("嫦娥\d号","嫦娥2号发射成功")
print(ret.group())
ret = re.match("嫦娥\d号","嫦娥3号发射成功")
print(ret.group())
Copy
运行结果:
嫦娥1号
嫦娥2号
嫦娥3号
嫦娥1号
嫦娥2号
嫦娥3号
Copy
示例4:\D
import re
match_obj = re.match("\D", "f")
if match_obj:
# 获取匹配结果
print(match_obj.group())
else:
print("匹配失败")
Copy
运行结果:
f
Copy
示例5:\s
import re
# 空格属于空白字符
match_obj = re.match("hello\sworld", "hello world")
if match_obj:
result = match_obj.group()
print(result)
else:
print("匹配失败")
# \t 属于空白字符
match_obj = re.match("hello\sworld", "hello\tworld")
if match_obj:
result = match_obj.group()
print(result)
else:
print("匹配失败")
Copy
运行结果:
hello world
hello world
Copy
示例6:\S
import re
match_obj = re.match("hello\Sworld", "hello&world")
if match_obj:
result = match_obj.group()
print(result)
else:
print("匹配失败")
match_obj = re.match("hello\Sworld", "hello$world")
if match_obj:
result = match_obj.group()
print(result)
else:
print("匹配失败")
Copy
运行结果:
hello&world
hello$world
Copy
示例7:\w
import re
# 匹配非特殊字符中的一位
match_obj = re.match("\w", "A")
if match_obj:
# 获取匹配结果
print(match_obj.group())
else:
print("匹配失败")
Copy
执行结果:
A
Copy
示例8:\W
# 匹配特殊字符中的一位
match_obj = re.match("\W", "&")
if match_obj:
# 获取匹配结果
print(match_obj.group())
else:
print("匹配失败")
Copy
执行结果:
&
Copy
小结
- . 表示匹配任意1个字符(除了\n)
- [ ] 表示匹配[ ]中列举的1个字符
- \d 表示匹配一个数字,即0-9
- \D 表示匹配一个非数字,即不是数字
- \s 表示匹配一个空白字符,即 空格,tab键
- \S | 匹配一个非空白字符
- \w | 匹配一个非特殊字符,即a-z、A-Z、0-9、_、汉字
- \W | 匹配一个特殊字符,即非字母、非数字、非汉字
匹配多个字符
1. 匹配多个字符
代码 | 功能 |
---|---|
* | 匹配前一个字符出现0次或者无限次,即可有可无 |
+ | 匹配前一个字符出现1次或者无限次,即至少有1次 |
? | 匹配前一个字符出现1次或者0次,即要么有1次,要么没有 |
{m} | 匹配前一个字符出现m次 |
{m,n} | 匹配前一个字符出现从m到n次 |
示例1:*
需求:匹配出一个字符串第一个字母为大小字符,后面都是小写字母并且这些小写字母可 有可无
import re
ret = re.match("[A-Z][a-z]*","M")
print(ret.group())
ret = re.match("[A-Z][a-z]*","MnnM")
print(ret.group())
ret = re.match("[A-Z][a-z]*","Aabcdef")
print(ret.group())
Copy
运行结果:
M
Mnn
Aabcdef
Copy
示例2:+
需求:匹配一个字符串,第一个字符是t,最后一个字符串是o,中间至少有一个字符
import re
match_obj = re.match("t.+o", "two")
if match_obj:
print(match_obj.group())
else:
print("匹配失败")
Copy
运行结果:
two
Copy
示例3:?
需求:匹配出这样的数据,但是https 这个s可能有,也可能是http 这个s没有
import re
match_obj = re.match("https?", "http")
if match_obj:
print(match_obj.group())
else:
print("匹配失败")
Copy
运行结果:
https
Copy
示例4:{m}、{m,n}
需求:匹配出,8到20位的密码,可以是大小写英文字母、数字、下划线
import re
ret = re.match("[a-zA-Z0-9_]{6}","12a3g45678")
print(ret.group())
ret = re.match("[a-zA-Z0-9_]{8,20}","1ad12f23s34455ff66")
print(ret.group())
Copy
运行结果:
12a3g4
1ad12f23s34455ff66
Copy
2. 小结
- *表示匹配前一个字符出现0次或者无限次,即可有可无
- +表示匹配前一个字符出现1次或者无限次,即至少有1次
- ?表示匹配前一个字符出现1次或者0次,即要么有1次,要么没有
- {m}表示匹配前一个字符出现m次
- {m,n}表示匹配前一个字符出现从m到n次