目录
- [1 正则匹配](#1 正则匹配)
-
- 注意点1
- [1.1 正则匹配字符串写法](#1.1 正则匹配字符串写法)
- [1.2 创建re函数](#1.2 创建re函数)
-
- (1)re.search()--搜索第一个匹配项
- [(2)re.match() - 从字符串开头匹配](#(2)re.match() - 从字符串开头匹配)
- [(3)re.findall() - 返回所有匹配项的列表](#(3)re.findall() - 返回所有匹配项的列表)
- [(4)re.finditer() - 返回匹配项的迭代器(适合大文本)](#(4)re.finditer() - 返回匹配项的迭代器(适合大文本))
- [(5)re.sub() - 替换匹配内容](#(5)re.sub() - 替换匹配内容)
- [(6)re.split() - 按正则表达式分割字符串](#(6)re.split() - 按正则表达式分割字符串)
- [2 参数数量/类型/默认值指定](#2 参数数量/类型/默认值指定)
- [3 引用传递和值传递说明](#3 引用传递和值传递说明)
- [4 排列组合 itertools](#4 排列组合 itertools)
- [5 内置变量/特殊变量](#5 内置变量/特殊变量)
-
- [5.1 内置变量](#5.1 内置变量)
- [5.2 类相关的特殊属性](#5.2 类相关的特殊属性)
- [6 try-except-else-finally机制](#6 try-except-else-finally机制)
-
- [6.1 基础用法](#6.1 基础用法)
- [6.2 else-finally](#6.2 else-finally)
- [6.3 向上一级抛出错误](#6.3 向上一级抛出错误)
- [7 Threading - 线程(不是进程,创建进程我用的少)](#7 Threading - 线程(不是进程,创建进程我用的少))
-
- [7.1 讲到线程,就不得不谈线程通信](#7.1 讲到线程,就不得不谈线程通信)
- [8 路径操作及路径索引 glob](#8 路径操作及路径索引 glob)
以下资料参考官网及AI
1 正则匹配
python 的 re 库能够实现正则匹配功能。
注意点1
注意:在Python中使用正则表达式时要优先使用原始字符串。
(也就是说,字符串不会被python语言解析。而只会被re库里的函数解析)
原因如下:
正则表达式本身用 \ 转义特殊字符(如 \d 表示数字),但Python字符串中的 \ 也是转义符。因此,在普通字符串中写正则表达式时,需用 两个反斜杠 表示一个实际的反斜杠(如 \d)。
原始字符串(前缀 r)会忽略Python字符串的转义规则,直接保留所有字符的字面值。例如,r"\d" 会直接传递给正则引擎 \d,而无需额外转义。
以下为错误案例1:
python
import re
pattern = "\\" # 普通字符串:实际传递的是单个 \,但正则引擎会报错(转义不完整)
re.findall(pattern, "a\\b") # 报错:因为正则收到的是单个 \
正确写法:
python
pattern = "\\\\" # 普通字符串中,四个反斜杠 → Python转义为两个 \,正则引擎收到两个 \
result = re.findall(pattern, "a\\b") # 成功匹配到 ["\\"]
使用原始字符串的写法:
python
pattern = r"\\" # 原始字符串直接保留两个 \,正则引擎收到两个 \
result = re.findall(pattern, "a\\b") # 成功匹配到 ["\\"]
以下为错误案例2:
python
pattern = "\b" # 普通字符串中,\b 是退格符,正则引擎无法识别为单词边界
re.findall(pattern, "hello world") # 匹配失败
正确写法:
python
pattern = r"\b" # 原始字符串直接传递 \b,正则引擎识别为单词边界
result = re.findall(pattern, "hello world") # 匹配到单词边界的空字符
1.1 正则匹配字符串写法
pattern = r'xxx'
匹配字符 | 含义 | 案例 |
---|---|---|
[ ] | 一个字符的集合,这写字符可以单独列出,也可以用范围表示(范围用- 分隔) |
[abc],[a-c] |
$ | [akm\] 将会匹配以下任一字符 'a', 'k', 'm' 或 '' | |
^ | 把 ^ 放在字符类的最开头,集合取反来匹配字符类中未列出的字符。(如果放在字符类其他位置,则无意义) |
[^5] 将匹配除 '5' 之外的任何字符;[5^] 将匹配 '5' 或 '^' |
\w | 匹配任何字母数字字符 | 相当于字符类 [a-zA-Z0-9_] |
\d | 匹配任何十进制数字 | 等价于字符类 [0-9] |
\S | 匹配任何非空白字符 | 等价于字符类 [^ \t\n\r\f\v] |
\W | 匹配任何非字母与数字字符 | 等价于字符类 [^a-zA-Z0-9_] |
\s | 匹配任何空白字符 | [ \t\n\r\f\v] |
\D | 匹配任何非数字字符 | 等价于字符类 [^0-9] |
. | 匹配除换行符之外的任何字符 | |
* | 定前一个字符可以匹配零次或更多次,而不是只匹配一次 | ca*t 将匹配 'ct' ( 0 个 'a' )、'cat' ( 1 个 'a' )、 'caaat' ( 3 个 'a' ) |
+ | 匹配一次或更多次 | ca+t 可以匹配 'cat' ( 1 个 'a' )或 'caaat' ( 3 个 'a'),但不能匹配 'ct' |
{m,n} | 其中 m 和 n 是十进制整数,该限定符意味着必须至少重复 m 次,最多重复 n 次。 | a/{1,3}b 可以匹配 'a/b'、'a//b' 或者 'a///b' ,但不能匹配中间没有斜杆的 'ab',或者四个斜杆的 'ab' |
() | 它们将包含在其中的表达式组合在一起,你可以使用重复限定符重复组的内容 | (ab)*,匹配ab 0到多次 |
1.2 创建re函数
(1)re.search()--搜索第一个匹配项
python
import re
text = "Python is fun, Python is powerful"
pattern = r"Python"
match = re.search(pattern, text)
if match:
print("Found:", match.group()) # 输出: Found: Python
(2)re.match() - 从字符串开头匹配
python
import re
text = "Python is awesome"
pattern = r"Python"
match = re.match(pattern, text)
if match:
print("Match found:", match.group()) # 输出: Match found: Python
# 若 text = "I love Python",则 match 为 None
(3)re.findall() - 返回所有匹配项的列表
python
import re
text = "apple 12, banana 3, cherry 45"
numbers = re.findall(r'\d+', text)
print(numbers) # 输出: ['12', '3', '45']
(4)re.finditer() - 返回匹配项的迭代器(适合大文本)
python
import re
text = "a=1, b=2, c=3"
matches = re.finditer(r'\w+=\d+', text)
for match in matches:
print(match.group()) # 输出: a=1, b=2, c=3
(5)re.sub() - 替换匹配内容
python
import re
text = "2023-10-05"
new_text = re.sub(r'-', '/', text)
print(new_text) # 输出: 2023/10/05
# 使用函数处理替换内容
def double_number(match):
return str(int(match.group()) * 2)
text = "Score: 5, Count: 3"
result = re.sub(r'\d+', double_number, text)
print(result) # 输出: Score: 10, Count: 6
(6)re.split() - 按正则表达式分割字符串
python
import re
text = "one,two;three four"
parts = re.split(r'[,; ]+', text)
print(parts) # 输出: ['one', 'two', 'three', 'four']
2 参数数量/类型/默认值指定
直接通过一个综合案例说明:
python
from typing import Union, Optional, Any
def generate_user_card(
username: str, # 必选参数(无默认值)
age: int = 18, # 必选但有默认值(可省略)
*hobbies: str, # 不定数量的位置参数(爱好)
country: Optional[str] = "未知", # 可选关键字参数(允许None)
**extra_info: Union[str, int, float] # 不定数量的关键字参数(扩展信息)
) -> dict[str, Any]:
"""
生成用户信息卡,支持灵活参数输入
"""
user_data = {
"username": username,
"age": age,
"hobbies": hobbies if hobbies else ("无",),
"country": country,
"extra": extra_info
}
return user_data
(1)基础调用:
python
result1 = generate_user_card("Alice")
print(result1)
# {'username': 'Alice', 'age': 18, 'hobbies': ('无',), 'country': '未知', 'extra': {}}
(2)额外信息传入:
python
result3 = generate_user_card(
"Charlie",
age=30,
country=None, # 明确设置为None
email="[email protected]",
score=95.5
)
print(result3["extra"])
# {'email': '[email protected]', 'score': 95.5}
3 引用传递和值传递说明
在 Python 中,变量传递的本质是 对象引用的传递,所有操作都是基于对象的引用(可以理解为"指针")。
-
不可变对象(int, float, str, tuple 等)
传递的是对象的引用,但修改时会创建新对象,原始对象不受影响(类似"值传递"的效果)。
-
可变对象(list, dict, set, 自定义类实例等)
传递的是对象的引用,修改内容时会影响原始对象(类似"引用传递"的效果)。
案例说明1
python
def modify_data(num: int, lst: list, obj: object):
num += 10 # 不可变对象:创建新对象
lst.append(4) # 可变对象:修改原对象
obj.value = 5 # 可变对象:修改原对象
# 初始化数据
original_num = 5
original_list = [1, 2, 3]
class MyClass:
def __init__(self):
self.value = 0
original_obj = MyClass()
# 调用函数
modify_data(original_num, original_list, original_obj)
print(original_num) # 输出 5(未改变)
print(original_list) # 输出 [1, 2, 3, 4](已改变)
print(original_obj.value) # 输出 5(已改变)
案例2
python
class DataHolder:
def __init__(self, data):
self.data = data # data 是可变/不可变对象的引用
# 不可变对象操作
holder1 = DataHolder(10)
temp = holder1.data
temp += 5 # 创建新对象,不影响原数据
print(holder1.data) # 输出 10
# 可变对象操作
holder2 = DataHolder([1, 2])
holder2.data.append(3) # 直接修改原对象
print(holder2.data) # 输出 [1, 2, 3]
案例3:修改和赋值的本质区别
python
a = [1, 2]
b = a # 引用传递(指向同一对象)
b.append(3) # 修改原对象
print(a) # 输出 [1, 2, 3]
c = [4, 5]
d = c
d = [6, 7] # 创建新对象(重新绑定引用)
d.append(10)
print(c) # 输出 [4, 5](原对象未变)
注意,这里:
lst = lst + (创建新列表,不影响原对象)
lst.append(4)(原地修改,影响原对象)
案例4:默认参数陷阱
python
# 错误示例:默认参数为可变对象
def buggy_func(data=[]): # 默认列表会持续保留
data.append(1)
return data
# 正确做法
def safe_func(data=None):
data = data if data is not None else []
data.append(1)
return data
错误案例的进一步测试:
python
def func(data=[]):
data.append(1)
return data
func()
data = func()
data.append(10)
func()
print(data) # 输出:[1, 1, 10, 1]
4 排列组合 itertools
tee 生成迭代器副本(副本的修改不影响原始数据)
islice 切片
zip_longest 合并多个迭代器
python
import itertools
l = [1,2,3,4]
iter1, iter2 = itertools.tee(l, 2)
for x in iter1:
#
itertools.zip_longest()
5 内置变量/特殊变量
5.1 内置变量
python所有的内置变量:
python
dir(__builtins__)
__name__
如果当前运行的python文件为主文件,则该文件:
__name__ == __main__
如果当前文件被其他文件调用,则该文件:
__name__ == [文件名]
(不带.py后缀)
参考文章
5.2 类相关的特殊属性
__slots__
限制class可绑定的类的属性。
python
__slots__ = ['属性名1','属性名2','属性名3']
定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。
除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。
__init__
类默认构造函数 ,第一个参入参数为self
__lt__
@property装饰器
将方法变成属性调用。
__str__
6 try-except-else-finally机制
6.1 基础用法
python
try:
with open('example.txt', 'r') as file:
content = file.read()
print(content)
except FileNotFoundError:
print("文件未找到,请检查文件路径是否正确。")
except PermissionError:
print("没有权限读取该文件。")
except Exception as e:
# 捕获所有其他类型的异常
print(f"发生了一个错误:{e}")
try: 放置可能引发异常的代码。'
except:如果try中的代码引发异常,会跳转到指定的except 块儿中
as: as e是可选的,允许你将异常实例赋值给变量e,这样就可以在except块中访问到异常信息。
Exception :代表不指定异常类型(反之捕获所有异常)
Python会按照except块的顺序检查,一旦找到匹配的异常类型,就会执行该块中的代码,并且跳过后续的except块。
6.2 else-finally
python
try:
# 尝试执行的代码
pass
except SomeException:
# 处理异常的代码
pass
else:
# 如果没有异常发生,执行这里的代码
pass
finally:
# 无论是否发生异常,都执行这里的代码
pass
else:如果你想要在没有异常发生时执行一些代码,可以使用else块。它紧跟在所有的except块之后,只有在try块没有引发任何异常时才会执行。
finally:无论是否发生异常,finally块中的代码都会被执行。这通常用于执行一些清理工作,比如关闭文件或释放资源。
6.3 向上一级抛出错误
raise [error]
注意:如果不抛出错误,程序在执行换except后就会退出吗?
当except块内部的操作执行完成后,程序并不会自动退出,除非你在except块中显式地调用了sys.exit()、exit()、os._exit()等函数来终止程序,或者异常没有被捕获并且传播到了程序的顶层(即没有被任何try块捕获)。
7 Threading - 线程(不是进程,创建进程我用的少)
感谢大佬的总结:
https://liaoxuefeng.com/books/python/process-thread/thread/index.html
说实话,之前只用过C thread,没用过python。
这里对大佬的 文章列出一些关键点:
(1)启动一个线程就是把一个函数传入并创建Thread实例,然后==调用start()==开始执行。
(2)在Python中,可以使用多线程,但不要指望能有效利用多核
python
有一些久远的记忆似乎在逐渐复苏
7.1 讲到线程,就不得不谈线程通信
线程的特点就是,共享资源,任务间需要频繁通信。
线程的关键点就是:通信和同步。
要避免的问题:死锁
(1)互斥锁
(2)信号量
(3)条件变量
(4)事件
(5)消息队列
(6)管道
8 路径操作及路径索引 glob
主要利用glob2库
python
from glob2 import glob
paths = glob(file_path) # 搜索文件file_path下所有文件,返回list变量
# 返回该路径下所有文件