当前位置: 首页 > article >正文

IO编程与正则表达式

IO编程与正则表达式

  • 正则表达式
    • 定义
    • 组成
      • 普通字符
      • 元字符
      • 应用示例
    • re模块
      • 匹配:
      • 替换:
      • 分割:
      • 编译:
    • 切分字符串
    • 分组
    • 贪婪匹配
    • 编译
  • IO编程
    • 文件读写
      • 读文件
      • 写文件
    • StringIO与BytesIO
      • StringIO
      • BytesIO
    • 操作文件和目录
      • 操作文件
      • 操作目录
      • 其他文件和目录操作
    • 序列化
      • pickle模块实现序列化与反序列化
        • pickle.dumps()函数将对象转换为字节流
        • pickle.dump()将 Python 对象写入文件
      • pickle模块实现反序列化
        • pickle.loads()函数从字节流反序列化
        • pickle.load()从文件读取并反序列化 Python 对象
        • 自定义序列化
      • JSON实现序列化与反序列化
        • JSON转换Python对象
        • JSON将Python对象序列化写入文件
        • JSON读取文件反序列化
        • 自定义序列化及反序列化

正则表达式

定义

正则表达式(Regular Expression,简称 regex)是一种用于匹配字符串的工具,它定义了一种字符串的模式,通常用于查找、替换、验证等操作。

组成

正则表达式是由普通字符(例如a到z之间的字母)和特殊字符(称为“元字符”)组成的一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

普通字符

普通字符就是那些在正则表达式中直接表示其字面意义的字符。它们包括所有的ASCII字符和Unicode字符(取决于正则表达式的实现和使用的字符集)。例如,字母a到z、数字0到9、标点符号以及空格等都是普通字符。
在正则表达式中,普通字符匹配的就是它们自身。例如,正则表达式a匹配的就是字符串中的字符a。

元字符

.:匹配除换行符\n之外的任何单个字符。例如’py.‘可以匹配’pyc’、‘pyo’、'py!'等等。
^:匹配输入字符串的开始位置。如果设置了多行模式(multiline mode),则匹配每一行的开始。
$:匹配输入字符串的结束位置。如果设置了多行模式,则匹配每一行的结束。
*:匹配前面的子表达式零次或多次。例如,zo能匹配“z”以及“zoo”。
+:匹配前面的子表达式一次或多次。例如,zo+能匹配“zo”以及“zoo”,但不能匹配“z”。
?:匹配前面的子表达式零次或一次。例如,do(es)?可以匹配“do”或“does”。
{n}:n是一个非负整数,匹配前面的子表达式恰好n次。例如,o{2}不能匹配“Bob”中的“o”,但能匹配“food”中的两个o。
{n,}:n是一个非负整数,至少匹配n次。例如,o{2,}不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。o{1,}等价于o+。o{0,}等价于o

{n,m}:m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,o{1,3}将匹配“fooooood”中的前三个o。o{0,1}等价于o?。请注意在逗号和两个数之间不能有空格。
[]:字符集合。匹配所包含的任意一个字符。例如,[abc]可以匹配“plain”中的“a”。
[^]:负字符集合。匹配未包含的任意字符。例如,[^abc]可以匹配“plain”中的“p”和“l”。
|:或运算符。匹配左边或右边的表达式。例如,a|b可以匹配“a”或“b”。a|bc匹配“a”或“bc”。
():分组。将多个字符或表达式组合成一个单元,用于后续的引用或操作。例如,(abc)将“abc”作为一个整体来匹配。
\:转义字符。用于匹配那些具有特殊含义的字符,或表示那些不易直接在正则表达式中表示的字符。例如,.匹配点字符.本身,而\ 匹配美元符号 匹配美元符号 匹配美元符号
\b:匹配一个单词边界,即单词和空格之间的位置。例如,er\b可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B:匹配非单词边界。例如,er\B可以匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\d:匹配一个数字字符。等价于[0-9]。
\D:匹配一个非数字字符。等价于[^0-9]。
\s:匹配任何空白字符,包括空格、制表符、换页符等。等价于[ \f\n\r\t\v]。
\S:匹配任何非空白字符。等价于[^ \f\n\r\t\v]。
\w:匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]。
\W:匹配任何非单词字符。等价于[^A-Za-z0-9_]。

应用示例

\d{3}\s+\d{3,8}  # 匹配以任意个空格隔开的带区号的电话号码,例如:021 1234567
[0-9a-zA-Z\_]  # 可以匹配一个数字、字母或者下划线;
[0-9a-zA-Z\_]+  # 可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','Py3000'等等;
[a-zA-Z\_][0-9a-zA-Z\_]{0, 19}  # 更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。
py  # 可以匹配'python'
^py$  # 整行匹配,只能匹配'py'。

re模块

re模块是Python标准库中的一个内置模块,用于支持正则表达式操作。

匹配:

以下方法中pattern表示正则表达式,string表示要匹配的字符串
re.match(pattern, string, flags=0):尝试从字符串的起始位置匹配一个模式,如果匹配成功则返回一个匹配的对象,否则返回None。
re.search(pattern, string, flags=0):扫描整个字符串并返回第一个成功的匹配,如果匹配成功则返回一个匹配的对象,否则返回None。
re.findall(pattern, string, flags=0):在字符串中找到正则表达式所匹配的所有子串,并返回一个列表。
re.finditer(pattern, string, flags=0):在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

替换:

re.sub(pattern, repl, string, count=0, flags=0):在字符串中替换匹配的文本。可以指定替换目标、替换内容和替换次数等参数。
re.subn(pattern, repl, string, count=0, flags=0):与re.sub相同,但返回一个包含新字符串和替换次数的元组。

分割:

re.split(pattern, string, maxsplit=0, flags=0):按照能够匹配的子串将字符串分割后返回列表。

编译:

re.compile(pattern, flags=0):编译一个正则表达式模式,返回一个模式的可重用对象。

切分字符串

print(re.split(r'\s+', 'a b   c'))

['a', 'b', 'c']
s = re.split(r'[\s\,\;]+', 'a,b;; c  d')
print(s)

['a', 'b', 'c', 'd']

分组

正则表达式用()表示的就是要提取的分组(Group)。
比如,提取一串电话号码的区号和本地号码:

m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
print(m.group(1))
print(m.group(2))
print(m.groups())

010
12345
('010', '12345')

贪婪匹配

正则表达式默认匹配模式是贪婪匹配,即尽可能多的匹配。
匹配出数字后面的0:

rt = re.match(r'^(\d+)(0*)$', '102300').groups()
print(rt)

('102300', '')  # 这里\d+采用贪婪匹配,直接把后面的0全部匹配了,结果0*只能匹配空字符串了

rb = re.match(r'^(\d+?)(0*)$', '102300').groups()
print(rb)

('1023', '00')  # \d+?添加了?让\d+采用非贪婪匹配

编译

先预编译一条正则表达式,后面可以重复使用

re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
print(re_telephone.match('010-12345').groups())
print(re_telephone.match('010-12345').group())
print(re_telephone.match('010-12345').group(1))

('010', '12345')
010-12346
010

IO编程

IO编程(输入输出编程)指的是在计算机程序中处理输入和输出的方式。输入可以是从用户、文件、网络或其他设备读取数据,而输出是将数据写入到用户界面、文件、网络或设备。IO操作在程序中扮演着至关重要的角色,尤其是在处理大数据、网络通信和文件操作时。

在Python中,IO操作包括文件读写、网络通信、用户输入输出等。常见的IO编程技术有同步IO和异步IO。
同步IO是最常见的IO方式。在这种模式下,程序在执行IO操作时会等待操作完成后再继续执行后续代码。每当程序执行一个IO操作时,它会被阻塞,直到该操作完成。
异步IO是一种更高效的方式,尤其适用于需要处理大量IO操作(如网络请求或文件读取)的应用。在这种模式下,程序不会被阻塞。相反,IO操作会在后台执行,当操作完成时,程序可以通过回调函数或者事件循环来获取结果。

同步和异步的区别就在于是否等待IO执行的结果。好比你去麦当劳点餐,你说“来个汉堡”,服务员告诉你,对不起,汉堡要现做,需要等5分钟,于是你站在收银台前面等了5分钟,拿到汉堡再去逛商场,这是同步IO。

你说“来个汉堡”,服务员告诉你,汉堡需要等5分钟,你可以先去逛商场,等做好了,我们再通知你,这样你可以立刻去干别的事情(逛商场),这是异步IO。

⚠️本文的IO编程是同步模式!!!

文件读写

读写文件的原理:
在磁盘上读写文件的功能都是由操作系统提供的,程序不能直接操控磁盘。所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。

读文件

打开文件对象:

f = open("D:/Code/project/PythonPractices/test.txt", "r")  # "r"表示读

此时文件夹里没有test.txt文件,运行程序报错:
在这里插入图片描述
新建一个test.txt文件,内容为:IO编程测试
运行程序没有报错也没有输出,说明已经成功打开了文件对象,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示:

f = open("D:/Code/project/PythonPractices/test.txt", "r", encoding="utf-8")  # encoding="utf-8"设置编码方式,防止输出乱码
print(f.read())

在这里插入图片描述
文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的:

f = open("D:/Code/project/PythonPractices/test.txt", "r", encoding="utf-8")
print(f.read())
f.close()

为了保证无论是否出错都可以关闭文件,可以采用try…finally:

try:
    f = open("D:/Code/project/PythonPractices/test.txt", "r", encoding="utf-8")
    print(f.read())
finally:
    if f:
        f.close()
        print("文件关闭")

Python引入了with语句来自动帮我们调用close()方法,可以简洁地实现上面try…finally的效果:

with open("D:/Code/project/PythonPractices/test.txt", "r", encoding="utf-8") as f:
    print(f.read())

读取文件内容时可以根据文件大小选择合适的读取方式:

  1. 如果文件很小,read()一次性读取最方便;
  2. 如果不能确定文件大小,反复调用read(size)比较保险;
with open("D:/Code/project/PythonPractices/test.txt", "r", encoding="utf-8") as f:
    print(f.read(3))

在这里插入图片描述

  1. 如果是配置文件,调用readlines()最方便:
with open("D:/Code/project/PythonPractices/test.txt", "r", encoding="utf-8") as f:
    for line in f.readlines():
        print(line.strip())  # 把末尾的'\n'删掉

在这里插入图片描述
要读取二进制文件,比如图片、视频等等,用’rb’模式打开文件即可:

f = open('/Users/michael/test.jpg', 'rb')
f.read()

写文件

f = open("D:/Code/project/PythonPractices/test.txt", "w", encoding="utf-8")
f.write("Hello World!")
f.close()

使用with语句,传入参数“a”在文件末尾追加写入:

with open("D:/Code/project/PythonPractices/test.txt", "a", encoding="utf-8") as f:
    f.write("hello world!")

StringIO与BytesIO

StringIO

StringIO 是 Python 标准库 io 模块中的一个类,用于在内存中操作字符串,模拟文件的读取和写入操作。
getvalue()方法用于获得写入后的str

from io import StringIO


Sf = StringIO()
Sf.write("hello world!")
print(Sf.getvalue())

在这里插入图片描述

BytesIO

BytesIO用于在内存中处理字节流

from io import BytesIO

Bf = BytesIO()
Bf.write("中文".encode("utf-8"))
print(Bf.getvalue())
print(Bf.getvalue().decode("utf-8"))

在这里插入图片描述
注意:这里写入的不是str,而是经过UTF-8编码的bytes

操作文件和目录

在 Python 中,操作文件和目录通常使用内置的 os 和 shutil 模块。os 模块提供了文件和目录的基本操作功能,而 shutil 模块则提供了更高级的文件和目录操作工具。

操作文件

  1. open()函数读取和写入文件,如上面所述
  2. 复制文件
import shutil

# 复制文件
shutil.copy('example.txt', 'example_copy.txt')

# 复制并保留元数据
shutil.copy2('example.txt', 'example_copy2.txt')
  1. 删除文件
import os

# 删除文件
os.remove('example.txt')
  1. 移动文件
import shutil

# 移动文件
shutil.move('example.txt', 'new_directory/example.txt')

# 重命名文件
shutil.move('old_name.txt', 'new_name.txt')

  1. 检查文件是否存在
import os

# 检查文件是否存在
if os.path.exists('example.txt'):
    print("File exists")
else:
    print("File does not exist")

  1. 获取文件信息
import os

# 获取文件大小
file_size = os.path.getsize('example.txt')
print(f"File size: {file_size} bytes")

# 获取文件的最后修改时间
mod_time = os.path.getmtime('example.txt')
print(f"Last modified: {mod_time}")

操作目录

  1. 创建目录
import os

# 创建单个目录
os.mkdir('new_directory')

# 创建多层目录
os.makedirs('parent_directory/sub_directory')

  1. 删除目录
import os
import shutil

# 删除空目录
os.rmdir('empty_directory')

# 删除非空目录
shutil.rmtree('non_empty_directory')

  1. 列出目录中的文件
import os

# 列出目录中的所有文件和目录
files = os.listdir('some_directory')
print(files)

from pathlib import Path

# 获取目录内容
path = Path('some_directory')
for item in path.iterdir():
    print(item)

  1. 检查目录是否存在
import os

# 检查目录是否存在
if os.path.exists('some_directory'):
    print("Directory exists")
else:
    print("Directory does not exist")

  1. 改变当前工作目录
import os

# 改变当前工作目录
os.chdir('some_directory')

# 获取当前工作目录
current_directory = os.getcwd()
print(current_directory)

  1. 获取父目录或祖父目录
from pathlib import Path

# 获取父目录
path = Path('some_directory/file.txt')
parent_dir = path.parent
print(parent_dir)

# 获取祖父目录
grandparent_dir = path.parent.parent
print(grandparent_dir)

其他文件和目录操作

  1. 获取文件的绝对路径、目录路径等
import os

# 获取绝对路径
absolute_path = os.path.abspath('example.txt')
print(f"Absolute path: {absolute_path}")

# 获取文件名
file_name = os.path.basename(absolute_path)
print(f"File name: {file_name}")

# 获取文件所在的目录
directory_name = os.path.dirname(absolute_path)
print(f"Directory: {directory_name}")

  1. 判断是否为文件或目录
import os

# 判断路径是否为文件
if os.path.isfile('example.txt'):
    print("It is a file")

# 判断路径是否为目录
if os.path.isdir('some_directory'):
    print("It is a directory")

  1. 复制目录
import shutil

# 复制目录及其内容
shutil.copytree('source_directory', 'destination_directory')

序列化

我们把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling。序列化的目的是将复杂的对象(如 Python 对象)转换为字节流、字符串或其他格式,以便在网络上传输、存储到磁盘或其他地方。常见的序列化格式包括 JSON、Pickle、YAML、XML 等。反过来,反序列化是将存储或传输的数据格式还原为原始数据结构的过程。

pickle模块实现序列化与反序列化

pickle方式只适用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。

pickle.dumps()函数将对象转换为字节流
import pickle

# Python 对象
data = {
    'name': 'Alice',
    'age': 30,
    'is_student': False
}

print(pickle.dumps(data))

输出结果:

D:\Code\project\PythonPractices\venv\Scripts\python.exe D:\Code\project\PythonPractices\IOtest.py 
b'\x80\x04\x95*\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x05Alice\x94\x8c\x03age\x94K\x1e\x8c\nis_student\x94\x89u.'

Process finished with exit code 0

pickle.dump()将 Python 对象写入文件
import pickle

# Python 对象
data = {
    'name': 'Alice',
    'age': 30,
    'is_student': False
}

# print(pickle.dumps(data))

# 将对象序列化并写入文件
with open('data.txt', 'wb') as f:
    pickle.dump(data, f)

data.txt文件中是一串乱码
在这里插入图片描述

pickle模块实现反序列化

pickle.loads()函数从字节流反序列化
import pickle

# Python 对象
data = {
    'name': 'Alice',
    'age': 30,
    'is_student': False
}

p = pickle.dumps(data)
print(pickle.loads(p))

输出结果:

D:\Code\project\PythonPractices\venv\Scripts\python.exe D:\Code\project\PythonPractices\IOtest.py 
{'name': 'Alice', 'age': 30, 'is_student': False}

Process finished with exit code 0

pickle.load()从文件读取并反序列化 Python 对象
import pickle

# 反序列化
with open('data.txt', 'rb') as f:
    loaded_data = pickle.load(f)

print(loaded_data)

输出结果:

D:\Code\project\PythonPractices\venv\Scripts\python.exe D:\Code\project\PythonPractices\IOtest.py 
{'name': 'Alice', 'age': 30, 'is_student': False}

Process finished with exit code 0

自定义序列化
import pickle

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __getstate__(self):
        # 返回一个可序列化的字典
        return {'name': self.name, 'age': self.age}

    def __setstate__(self, state):
        # 反序列化时重建对象
        self.name = state['name']
        self.age = state['age']

# 创建对象
person = Person('Alice', 30)

# 序列化
pickled_data = pickle.dumps(person)
print(pickled_data)

# 反序列化
loaded_person = pickle.loads(pickled_data)
print(loaded_person.name, loaded_person.age)

JSON实现序列化与反序列化

JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:

JSON类型Python类型
{}dict
[]list
“string”str
123.4int/float
true/falseTrue/False
nullNone
JSON转换Python对象
import json

# Python 对象
data = {
    'name': 'Alice',
    'age': 30,
    'is_student': False
}

# 序列化为 JSON 格式
json_data = json.dumps(data)
print("json_data:", json_data)

# 反序列化 JSON 格式为 Python 对象
data_parsed = json.loads(json_data)
print("data_parsed:", data_parsed)

json_data: {"name": "Alice", "age": 30, "is_student": false}
data_parsed: {'name': 'Alice', 'age': 30, 'is_student': False}

Process finished with exit code 0

JSON将Python对象序列化写入文件
import json

# Python 对象
data = {
    'name': 'Alice',
    'age': 30,
    'is_student': False
}

with open('data.json', 'w') as f:
    json.dump(data, f)
    print("写入成功")

with open('data.json', 'r') as f:
    print(f.read())

输出结果:

写入成功
{"name": "Alice", "age": 30, "is_student": false}
JSON读取文件反序列化
with open('data.json', 'r') as f:
    data_parsed = json.load(f)
    print(data_parsed)
    print(type(data_parsed))

输出结果:

{'name': 'Alice', 'age': 30, 'is_student': False}
<class 'dict'>
自定义序列化及反序列化
import json

class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score
    def to_dict(self):
        return {'name': self.name, 'age': self.age}

def dict_to_student(d):
    return Student(d['name'], d['age'], d['score'])


s = Student('Alice', 30, 90)
print(json.dumps(s, default=lambda obj: obj.to_dict()))
# 输出:{"name": "Alice", "age": 30, "score": 90}

json_str = json.dumps(s, default=lambda obj: obj.to_dict())
print(json.loads(json_str, object_hook=dict_to_student))
# 输出:<__main__.Student object at 0x0000017DE0A73510>

http://www.kler.cn/a/469503.html

相关文章:

  • 9. C 语言 循环控制结构详解
  • C# 修改项目类型 应用程序程序改类库
  • 点击主图,触发的是查看产品详情的逻辑
  • nginx配置 - 资源参数配置(性能优化)
  • 前端小案例——520表白信封
  • pip error: microsoft visual c++ 14.0 or greater is required
  • 保姆级教程Docker部署MySQL镜像
  • 网络安全的主要防护对象有哪些?
  • Oracle删除归档日志
  • Mysql数据实时同步到Es上
  • Harmony tab的使用
  • 2025年大数据、通信技术与计算机应用国际学术会议(BDCTA 2025)
  • GPTs+PRA:教育领域的新引擎,推动个性化与智能化教学
  • 量子机器学习:当量子计算遇上人工智能,颠覆即将来临?
  • Ubuntu20.04版本的ROS环境配置与基本概述
  • 生成式AI与RAG架构:如何选择合适的向量数据库?
  • TLS(传输层安全,Transport Layer Security)是用于在网络上提供通信安全的一种加密协议。
  • 【整理集合大全】MySQL(4) 数据库增删改查SQL语句
  • pytorch 梯度判断函数介绍
  • 【生活】冬天如何选口罩(医用口罩,N95, KN95还是KP95?带不带呼吸阀门?带不带活性炭?)
  • leetcode hot 100 只出现一次的数字
  • uniapp - 基于uniapp+vue3实现自定义增强版table表格组件体验「兼容H5+小程序+App端」
  • DooTask | 使用 DooTask AI 机器人,解锁任务创建新姿势
  • 使用Chrome谷歌浏览器中内置翻译功能
  • DVWA 命令注入写shell记录
  • 算法-excel表头位置转成对应数字 26进制转10进制