Skip to content
返回

Python 基础知识

AI 总结

本文介绍了 Python 的基础语法和常用数据结构,包括变量类型、字符串操作、列表、元组、字典、集合、条件判断、循环控制、异常处理等。还讲解了正则表达式的使用,以及如何通过列表生成式和迭代器高效处理数据。

Python 的名字来源于吉多所喜爱的电视剧 《蒙提·派森的飞行马戏团》,而不是蟒蛇。

当在 Python 中输入 import this 会看到下面文字:

优美胜于丑陋,明确胜于隐晦,简洁胜于复杂。 ——The Zen of Python, by Tim Peters

1989 年荷兰龟叔(吉多)打发圣诞假期时间,决定写一门新语言
1994 年发布 1.0
2000 年发布 2.0,2020 年 1 月停止维护
2008 年发布 3.0

目录

数据类型

Python 是弱类型语言,变量不需要声明类型,变量可以随时赋值为不同类型的数据。

# 整数
age = 18
largeNumber = 1_000_000_000

# 不同进制的表示
binary = 0b1010   # 0b开头表示二进制数,等于十进制的10
hex_num = 0xFF    # 0x开头表示十六进制数,等于十进制的255

# 浮点数
height = 1.75

# 科学计数法表示
light_speed = 3e8  # 光速:3 × 10^8 米/秒
atom_size = 1e-10  # 原子大小:1 × 10^-10 米

# 基本字符串
name = "小明"     # 使用双引号
greeting = '你好'  # 使用单引号
print(f"{name}说:{greeting}")  # 输出:小明说:你好

# 使用转义字符 \ 来表示特殊字符
message = "他说:\"Python很有趣!\""  # 使用转义字符

# 三引号字符串
# 可以包含多行文本,保留所有的换行和空格
# 适合编写文档字符串、多行文本等
long_text = """这是一个多行字符串,
不需要使用特殊的转义字符。"""

# 基本布尔值
is_sunny = True    # 今天天气晴朗
is_raining = False # 今天没有下雨

# 比较运算
age = 18
can_vote = age >= 18  # 判断是否达到投票年龄
print(f"可以投票吗?{can_vote}")  # 输出:可以投票吗?True

# 逻辑运算
# 逻辑运算符:and、or、not
# 逻辑运算符用于组合多个条件
# and:所有条件都为True时,结果为True
# or:只要有一个条件为True,结果为True
# not:对条件取反

has_ticket = True
has_id = True
can_enter = has_ticket and has_id  # 需要同时满足两个条件
print(f"可以入场吗?{can_enter}")  # 输出:可以入场吗?True

# 空值的使用
student_name = None  # 表示学生姓名暂时未知
print(f"学生姓名:{student_name}")  # 输出:学生姓名:None

# 多个变量同时赋值
x, y, z = 1, 2, 3
print(f"x={x}, y={y}, z={z}")  # 输出:x=1, y=2, z=3

# 变量的交换
a = 1
b = 2
a, b = b, a  # 交换a和b的值
print(f"a={a}, b={b}")  # 输出:a=2, b=1

# 使用type()函数查看变量的类型
print(type(score))  # 输出:<class 'int'>
print(type(name))   # 输出:<class 'str'>
print(type(is_passed))  # 输出:<class 'bool'>

字符串

## 字符串和数字的拼接
# 字符串和数字拼接时,不能直接拼接,需要先将数字转换为字符串
age = 20
message = "我今年" + str(age) + ""
print(message)  # 输出:我今年20岁

# 字符串重复
laugh = "" * 5  # 字符串可以和数字相乘,表示重复
print(laugh)  # 输出:哈哈哈哈哈

# 字符串不可变的例子
s = "hello"
s2 = s.replace("h", "H")
print(s)   # 输出:hello(原字符串没变)
print(s2)  # 输出:Hello(新字符串)

# 索引
word = "Python"
print(word[0])  # 输出第一个字符:P
print(word[-1]) # 输出最后一个字符:n

# 切片
greeting = "Hello, world!"
print(greeting[0:5])   # 输出:Hello(从第0到第4个字符,不包括第5个)
print(greeting[7:])    # 输出:world!(从第7个字符到结尾)
print(greeting[:5])    # 输出:Hello(从开头到第4个字符)

# 大小写转换
text = "Python is Fun!"
print(text.lower())  # 全部转为小写:python is fun!
print(text.upper())  # 全部转为大写:PYTHON IS FUN!

# 查找和替换
sentence = "I love apples, apples are sweet."
print(sentence.find("apples"))  # 查找'apples'第一次出现的位置,输出:7
print(sentence.replace("apples", "oranges"))  # 替换所有'apples'为'oranges'

# 百分号格式化
name = "小红"
age = 20
# 这是Python中的百分号格式化字符串方法
# %s 是一个占位符,表示将被字符串替换
# %d 是一个占位符,表示将被整数替换
# 括号中的(name, age)是要插入到字符串中的变量
# 变量会按顺序替换占位符:name替换%s,age替换%d
print("大家好,我叫%s,今年%d岁。" % (name, age))  # %s表示字符串,%d表示整数

# 常见的格式化占位符:
# %s - 字符串
# %d - 整数
# %f - 浮点数
# %.2f - 保留两位小数的浮点数
# %% - 输出百分号本身

# format {} 占位
fruit = "香蕉"
price = 3.5
print("今天的{}价格是{}元一斤。".format(fruit, price))  # 用{}占位,后面用format填充

# f-string格式化
score = 98
student = "李雷"
print(f"{student}的考试成绩是{score}分。")  # 变量名直接写在{}里

# 小明的身高和体重
height = 1.75  # 单位:米
weight = 80.5  # 单位:千克
# 计算BMI指数,公式:体重 / (身高的平方)
bmi = weight / (height ** 2)
print(f"小明的BMI指数为:{bmi:.2f}")  # 保留两位小数

编码与解码

# 编码为UTF-8字节
msg = "你好,世界"
msg_bytes = msg.encode("utf-8")  # 编码为字节
print(msg_bytes)  # 输出:b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c'
# 解码回字符串
msg_str = msg_bytes.decode("utf-8")  # 解码为字符串
print(msg_str)  # 输出:你好,世界

# 遍历字符串
for char in "Python":
    print(char)  # 依次输出每个字符

# 判断字符串内容
email = "user@example.com"
print(email.startswith("user"))  # 判断是否以"user"开头,输出:True
print(email.endswith(".com"))    # 判断是否以".com"结尾,输出:True
print(email.isdigit())           # 判断是否全是数字,输出:False

在 Python 中,当程序执行过程中遇到错误时,会抛出异常。我们可以使用 try-except 语法来捕获并处理这些异常,避免程序崩溃。

# 错误示例:用GBK解码UTF-8字节
try:
    msg = "你好,世界"
    msg_bytes = msg.encode("utf-8")  # 编码为字节
    wrong_str = msg_bytes.decode("gbk")  # 这里会报错,因为尝试用GBK解码UTF-8编码的字节
except UnicodeDecodeError as e:
    # except 代码块:捕获并处理特定类型的异常
    # UnicodeDecodeError 是解码错误的异常类型
    # as e 将异常对象赋值给变量e,以便后续使用
    print("解码出错:", e)  # 打印错误信息
-- 2025 年 9 月 22 日止 --

列表 list

# 创建一个空列表
empty = []
print(len(empty))  # 输出:0

# 创建一个装水果的列表
fruits = ["苹果", "香蕉", "橙子"]
print(fruits)  # 输出整个列表:['苹果', '香蕉', '橙子']
# 查看列表中有多少个元素
print(len(fruits))  # 输出:3

# 索引从0开始,依次访问每个水果
print(fruits[0])  # 输出第一个元素:苹果
print(fruits[1])  # 输出第二个元素:香蕉

# 访问最后一个元素,可以用-1
print(fruits[-1])  # 输出倒数第一个元素:橙子
# 访问不存在索引的元素会报错
# print(fruits[3])  # 报错:IndexError: list index out of range

# 在列表末尾添加一个新水果
fruits.append("葡萄")
print(fruits)  # 输出:['苹果', '香蕉', '橙子', '葡萄']
# append一次只能添加一个元素
fruits.append("西瓜", "柠檬")  # 报错:TypeError: append() takes exactly one argument (2 given)

# 在指定位置插入一个水果,比如插到第2个位置(索引为1)
fruits.insert(1, "西瓜")
print(fruits)  # 输出:['苹果', '西瓜', '香蕉', '橙子', '葡萄']

# 删除最后一个水果
last = fruits.pop()
print(last)    # 输出被删除的水果:葡萄

# 删除指定位置的水果,比如删除第2个(索引为1)
removed = fruits.pop(1)
print(removed) # 输出被删除的水果:西瓜
print(fruits)  # 输出:['苹果', '香蕉', '橙子']

# 把第二个水果改成“柠檬”
fruits[1] = "柠檬"
print(fruits)  # 输出:['苹果', '柠檬', '橙子']

# 创建一个嵌套列表,类似二维表格
matrix = [
    [1, 2, 3],
    [4, 5, 6]
]
# 访问第二行第三列的元素
print(matrix[1][2])  # 输出:6

元组 tuple

# 创建一个元组,存放三种颜色
colors = ("红色", "绿色", "蓝色")
print(colors)  # 输出:('红色', '绿色', '蓝色')
# 访问元组的元素,和列表一样
print(colors[0])   # 输出:红色
print(colors[-1])  # 输出:蓝色

# 尝试修改元组的内容会报错
colors[1] = "黄色"  # 这一行会报错:TypeError: 'tuple' object does not support item assignment

# 元组中的列表内容可以修改
fruits = ("苹果", ["香蕉", "橙子"])
fruits[1][0] = "西瓜"
print(fruits)  # 输出:('苹果', ['西瓜', '橙子'])

# 注意:只有一个元素的元组要加逗号
single = (42,)
print(type(single))  # 输出:<class 'tuple'>

not_tuple = (42)
print(type(not_tuple))  # 输出:<class 'int'>

# 这是一个三层嵌套的列表
data = [
    ["Tom", "Jerry", "Spike"],
    ["Python", "Java", "C++"],
    ["Alice", "Bob", "Eve"]
]

# 取出"Tom"
print(data[0][0])  # 输出:Tom
# 取出"Java"
print(data[1][1])  # 输出:Java
# 取出"Eve"
print(data[2][2])  # 输出:Eve

# 判断变量是不是元组
a = ()
b = (1)
c = [2]
d = (3,)
e = (4, 5, 6)

print(isinstance(a, tuple))  # True,空元组
print(isinstance(b, tuple))  # False,b是整数
print(isinstance(c, tuple))  # False,c是列表
print(isinstance(d, tuple))  # True,只有一个元素的元组
print(isinstance(e, tuple))  # True,多个元素的元组

if 条件判断

age = 21  # 定义一个变量age,表示年龄

# 基础语法
if age >= 18:  # 如果年龄大于等于18
    print("你已经成年啦!")  # 满足条件时执行
    print("可以独立做很多事情。")  # 这行也会被执行
# 如果age小于18,这两行不会被执行

# elif 用法
score = 72

if score >= 90:
    print("优秀")
elif score >= 75:
    print("良好")
elif score >= 60:
    print("及格")
else:
    print("不及格")
# 程序会从上往下判断,遇到第一个满足条件的分支就执行,然后跳过后面的分支

# 如果用户输入的不是数字,int()会报错
user_input = input("请输入一个数字:")
try:
    number = int(user_input)  # 尝试转换为整数
    print("你输入的数字是:", number)
except ValueError:
    print("输入的内容不是有效的数字,请重新输入。")

# 判断一个列表是否有内容
numbers = [1, 2, 3]
if numbers:  # 非空列表会被当作True
    print("列表有内容")
else:
    print("列表是空的")

numbers2 = []
if numbers2:  # 空列表会返回False
    print("列表有内容")
else:
    print("列表是空的")

match

文字,多值,条件

# 假设我们要根据天气情况给出不同的建议
weather = "rainy"
# 使用match语句进行多分支判断
match weather:
    case "sunny":
        print("天气晴朗,适合出门散步。")  # 如果是晴天
    case "rainy":
        print("下雨了,记得带伞。")        # 如果是雨天
    case "snowy":
        print("下雪了,注意保暖。")        # 如果是雪天
    case _:
        print("无法识别的天气类型。")      # 其他情况
        
# 判断一个月份属于哪个季节
month = 4
match month:
    case 12 | 1 | 2:# 12月、1月、2月属于冬季
        print("冬季")
    case 3 | 4 | 5:# 3月、4月、5月属于春季
        print("春季")
    case 6 | 7 | 8:# 6月、7月、8月属于夏季
        print("夏季")
    case 9 | 10 | 11:# 9月、10月、11月属于秋季  
        print("秋季")
    case _:# 其他情况
        print("月份无效")
        
# 判断分数等级
score = 85

match score:
    case s if s >= 90:
        print("成绩优秀")
    case s if 80 <= s < 90:
        print("成绩良好")
    case s if 60 <= s < 80:
        print("成绩及格")
    case _:
        print("成绩不及格")

list

match seq:
	case [x, y, *rest]:
		return f"≥2 个元素:x={x}, y={y}, rest={rest}"
	case _:
		return "不匹配"

match nums:
	case [x, y, *rest] if x <= y and all(n >= 0 for n in rest):
		return f"非降序起步且其余非负:x={x}, y={y}, rest={rest}"
	case [x, *_, z] if z % 2 == 0:
		return f"以偶数 {z} 结尾"
	case _:
		return "其它"

# 先判断数据结构
def handle(msg):
    match msg:
        case {"kind": "pay", "amount": amt} if amt > 0:
            return f"支付 {amt}"
        case {"kind": "pay", "amount": amt} if amt <= 0:
            return "金额非法"
        case _:
            return "未知消息"

print(handle({"kind": "pay", "amount": 100}))   # 支付 100
print(handle({"kind": "pay", "amount": 0}))     # 金额非法
print(handle({"kind": "pay", "amount": -5}))    # 金额非法
print(handle({"kind": "refund", "amount": 50})) # 未知消息
print(handle({"foo": 1}))                       # 未知消息
print(handle(["pay", 100]))                     # 未知消息

循环

for … in …

# 假设有一个学生名单
students = ["小明", "小红", "小刚"]
# 用for循环依次打印每个学生的名字
for student in students:
    print(student)  # 每次循环,student变量会依次等于列表中的每个名字
    
# 计算1到10的累加和
total = 0  # 用于累加的变量
# 使用range()函数生成1到10的整数序列
# range()函数可以生成一个整数序列,包含从开始到结束(不包含结束)的整数
# 例如,range(1, 11)会生成1到10的整数序列
# range(5) 会生成0到4的整数序列 [0, 1, 2, 3, 4]
for number in range(1, 11):
    total += number  # 每次循环把当前数字加到total上
print("1到10的和是:", total)  # 输出:1到10的和是:55

list(range(5, 1, -1))  # [5, 4, 3, 2]
# 注意 stop 是开区间,不包含 1;想包含 1 用 range(5, 0, -1)

# for循环可用于循环字符串
for char in "Hello":
    print(char)

while (boolean)

# 用while循环打印1到5
n = 1
while n <= 5:  # 只要n小于等于5就继续循环
    print(n)
    n += 1  # 每次循环n加1

for … else

for i in range(2, 6):
    for j in range(2, i):
        if i % j == 0:
            break
    else:
        print(i, "是素数")   # 只有内层没 break 时才会打印

break & continue

# 打印1到100,但遇到第一个能被7整除的数就停止
for i in range(1, 101):
    if i % 7 == 0:  # 如果i能被7整除
        print("遇到第一个能被7整除的数:", i)
        break  # 立即结束整个循环
    print(i)

# 打印1到10中的所有奇数
for i in range(1, 11):
    if i % 2 == 0:  # 如果是偶数
        continue    # 跳过本次循环,后面的print不会执行
    print(i)        # 只会打印奇数

# 跳出多层的方式
for i in range(1, 4):
    for j in range(1, 4):
        if j == 2:
            break          # 只跳出内层 for j
        print(f"i={i}, j={j}")
print("done")

# 标志位跳出
found = False
for i in range(1, 6):
    for j in range(1, 6):
        if i * j == 12:
            found = True
            break          # 先跳出内层
    if found:
        break              # 再根据标志位跳出外层
print("结束于:", i, j)     # -> i=3, j=4

# retrun 跳出
def find_first_mul12():
    for i in range(1, 6):
        for j in range(1, 6):
            if i * j == 12:
                return i, j   # 直接从函数返回,等同跳出所有层
    return None

print(find_first_mul12())      # -> (3, 4)

# 抛出并捕获自定义异常
# 这种方式在需要从深层嵌套中“立即脱身”又不方便改函数结构时挺好用,但要注意可读性。
class BreakOut(Exception): pass

try:
    for i in range(1, 6):
        for j in range(1, 6):
            if i * j == 12:
                raise BreakOut((i, j))
except BreakOut as e:
    i, j = e.args[0]
    print("捕获到位置:", i, j)

O (1) vs O (n)

set / dict 里用 in 查找,通常不管集合多大,耗时都近似常数;而在 list 里,集合越大,查得越慢。

字典 mapping

book = {"title": "Fluent Python", "price": 88, ("pub","year"): 2021}
d = {"a": 1}

# 查
d["a"]          # 1;键不存在会 KeyError
d.get("x", 0)   # 0;更安全:给默认值
"x" in d        # False

# 增改
d["b"] = 2
d.update({"c": 3, "a": 9})   # 批量合并/覆盖
d |= {"d": 4}                # 3.9+ 合并运算
{**d, **{"e": 5}}            # 解包合并成新字典

# 删
del d["b"]
d.pop("c", None)             # 带默认值更稳
d.clear()                    # 清空

for k in d: ...              # 键
for k, v in d.items(): ...   # 键值对
d.keys(), d.values(), d.items()  # 动态“视图”,随字典变化而变

# 构造字典的优雅方式
squares = {x: x*x for x in range(5)}  # {0:0, 1:1, ...}

# 缺省值与计数的三种姿势

# 1) get
counts = {}
for ch in "banana":
    counts[ch] = counts.get(ch, 0) + 1

# 2) setdefault(返回并设置缺省)
d = {}
for k, v in [("a",1),("a",2)]:
    d.setdefault(k, []).append(v)

# 3) defaultdict(推荐频繁缺省场景)
from collections import defaultdict, Counter
dd = defaultdict(list)
for k, v in [("a",1),("a",2)]: dd[k].append(v)

集合 set

# 集合的元素必须是不可变类型,比如数字、字符串、元组
valid_set = {1, "hello", (2, 3)}
print(valid_set)  # 输出:{1, 'hello', (2, 3)}

# 不能把列表放进集合,否则会报错
wrong_set = {[1, 2, 3]}  # 这一行会报TypeError: unhashable type: 'list'

# 常用操作
s = {1, 2, 3}
s.add(4)             # {1,2,3,4}
s.update([3, 5, 6])  # {1,2,3,4,5,6}
s.discard(10)        # 删不存在的元素也不会报错
# s.remove(10)       # 不存在会 KeyError
x = s.pop()          # 随机弹出一个元素(因无序)

# 集合代数
a, b = {1,2,3}, {3,4,5}
a | b     # 并集 {1,2,3,4,5}
a & b     # 交集 {3}
a - b     # 差集 {1,2}
a ^ b     # 对称差 {1,2,4,5}

# 判断关系
{1,2} <= {1,2,3}     # 子集 True
{1,2,3}.issuperset({1,2})  # 超集 True
-- 2025 年 9 月 23 日止 --

切片 slice

# 切片对象
sl = slice(1, 5, 2)
[10,11,12,13,14,15][sl]   # [11, 13]

seq[start : stop : step]
# start  起始下标(含)
# stop   结束下标(不含)
# step   步长,默认 1,可为负

s = "abcdefg"
s[1:4]     # 'bcd'
s[:3]      # 'abc'
s[4:]      # 'efg'
s[::2]     # 'aceg'
s[-4:-1]   # 'def'
s[::-1]    # 'gfedcba'  反转

[1,2,3][0:10]   # [1,2,3]

# 赋值/删除切片(仅 list 等可变序列)
a = [0,1,2,3,4,5]
a[2:5] = [20, 30]      # → [0,1,20,30,5]   # 替换并缩短
a[2:2] = [7,8]         # → [0,1,7,8,20,30,5]  # 在索引 2 处插入
a[::2] = [9,9,9,9]     # 步长切片赋值,右侧长度必须匹配元素个数
del a[1:4]             # 删除片段

# 使用 sorted
# 创建一个学生成绩列表
scores = [85, 92, 78, 90, 88, 95, 82, 87, 91, 89]

# 获取前5名学生的成绩
# 使用sorted函数对scores列表进行排序,并使用reverse=True参数进行降序排序
# 然后使用切片[:5]获取前5名学生的成绩
top_five = sorted(scores, reverse=True)[:5]
print("前5名成绩:", top_five)  # 输出: [95, 92, 91, 90, 89]

# 获取后3名学生的成绩
# 使用sorted函数对scores列表进行排序,并使用reverse=False参数进行升序排序
# 然后使用切片[:3]获取后3名学生的成绩
bottom_three = sorted(scores)[:3]
print("后3名成绩:", bottom_three)  # 输出: [78, 82, 85]

迭代 iteration

# for x in obj 的幕后流程:

it = iter(obj)          # 调 __iter__ 得到迭代器
while True:
    try:
        x = next(it)    # 调 __next__
    except StopIteration:
        break
    # 使用 x
    
# 常用写法
for x in [1,2,3]: ...
for ch in "abc": ...
for k, v in {"a":1, "b":2}.items(): ...
for i in range(5): ...

# 带索引
for i, x in enumerate(["a","b","c"], start=1):
    ...

# 并行迭代
for a, b in zip([1,2,3], [10,20,30]):
    ...

# 推导式(语法糖,返回容器或集合)
squares = [x*x for x in range(10)]          # 列表推导
evens   = {x for x in range(10) if x%2==0}  # 集合推导
mapping = {x: x*x for x in range(5)}        # 字典推导

# 生成器函数:用 yield 按需产出元素;天然是迭代器。

def countdown(n):
    while n > 0:
        yield n   # 产出 n,并暂停在这里
        n -= 1    # 下次继续从这里往后跑

g = countdown(3)
next(g)     # 3
next(g)     # 2
next(g)     # 1
next(g)     # StopIteration 异常(迭代结束)

# 通常用 for 最方便:
for x in countdown(3):  # 3, 2, 1
    print(x)

# 列表推导(立即生成列表,占用对应内存)
lst = [x*x for x in range(10)]   # [0, 1, 4, ..., 81]

# 生成器表达式(惰性,不占大内存)
gen = (x*x for x in range(10))
print(next(gen))      # 0
print(next(gen))      # 1
print(list(gen))      # [4, 9, 16, 25, 36, 49, 64, 81]  # 把剩下的取完

# 生成器表达式是迭代器,只能遍历一次
# 遍历完后,再次遍历会抛出 StopIteration 异常
print(list(gen))      # []  已经耗尽
iterable_iter = iter([1,2,3])    # 从可迭代得到迭代器
next(iterable_iter)              # -> 1

# itertools 小而美(懒序列工具箱)
from itertools import islice, count, chain
# .count(start=0, step=1) 生成一个“无限等差序列”

# .islice 两种调用形式
# .islice(iterable, stop)    
# .islice(iterable, start, stop[, step])
# 对任意可迭代对象做“切片”,返回惰性子序列(像 `seq[start:stop:step]`,但不要求是序列)
print(list(islice(count(10, 2), 3)))  # [10, 12, 14]  无限序列切片

# .chain(*iterables) 把多个可迭代对象首尾相接,像把它们“串起来”
# 不会复制数据,逐个迭代。    
# 比 `sum(lists, [])` 拼接列表高效很多(后者有 O(n²) 拷贝风险)
list(chain([1,2], (3,4), {5,6}))      # [1, 2, 3, 4, 5, 6]
list(chain([1,2], [3,4]))             # [1,2,3,4]

列表生成式

用一行表达式构造列表的语法糖,等价于“循环 + 条件 + append

[ 表达式  for 变量 in 可迭代对象  if 条件 ]
# 等价于
out = []
for 变量 in 可迭代对象:
    if 条件:
        out.append(表达式)

# 平方表
squares = [x*x for x in range(6)]              # [0,1,4,9,16,25]

# 过滤:只要偶数的平方
even_sq = [x*x for x in range(10) if x % 2 == 0]  # [0,4,16,36,64]

# 条件表达式(内联三元运算)
labels = ["odd" if x % 2 else "even" for x in range(5)]
# 等价循环:if…else 放在表达式位置,不是过滤

# 笛卡尔积(所有配对)
pairs = [(i, j) for i in range(3) for j in range(2)]
# → [(0,0),(0,1),(1,0),(1,1),(2,0),(2,1)]  # 左到右依次展开

# 扁平化二维列表
matrix = [[1,2,3],[4,5,6]]
flat = [x for row in matrix for x in row]      # [1,2,3,4,5,6]

data = ["a","b","c"]
with_idx = [(i, x) for i, x in enumerate(data, start=1)]  # [(1,'a'),...]
zipped   = [a+b for a, b in zip("ABC", "xyz")]            # ['Ax','By','Cz']

# 集合推导:自动去重
s = {x % 3 for x in range(10)}                 # {0,1,2}

# 字典推导:键值对
d = {x: x*x for x in range(5)}                 # {0:0, 1:1, ...}

# 清洗数据:去空白并过滤空串
clean = [s.strip() for s in lines if s.strip()]

# 展开并过滤
words = [w.lower() for line in lines for w in line.split() if w]

# 仅保留字母数字
import re
norm = [re.sub(r"\W+", "", s) for s in strings]

# 海象运算符 := 表达式里复用中间结果
# n 只算一次,既做过滤又收集
sizes = [n for s in files if (n := s.stat().st_size) > 0]

正则表达式

一门描述文本模式的小语言,用来查找、提取、替换字符串中符合某种规则的片段。比如:匹配邮箱、手机号、日期、URL 等。

表达式符号

字面量与转义

断言

先行/后行(不消耗字符,只检查“前后邻居”)

常用 flags(模式修饰符)

import re

# 1) 查找
text = "2023-08-20 is a date, and 2024-01-01 is also a date."
m = re.search(r"\d{4}-\d{2}-\d{2}", text)  # 找第一个匹配
if m:
    m.group(0)   # 整个匹配
    m.start(), m.end()

# 2) 全部匹配
all_dates = re.findall(r"\d{4}-\d{2}-\d{2}", text)

# 3) 迭代匹配(更省内存 & 有位置信息)
for m in re.finditer(r"\b\w+\b", text):
    print(m.group(), m.span())

# 4) 替换
re.sub(r"\s+", " ", text)                   # 多空白折叠为单空格
s = "123-456-7890"
re.sub(r"(\d{3})-(\d{4})", r"\1 \2", s)     # 用分组反向引用

# 5) 分割
re.split(r"[,\s]+", "a,  b   c")            # -> ['a','b','c']

# 6) 预编译(频繁使用时更快)
pat = re.compile(r"\b([A-Za-z]+)=(\d+)\b")
pat.search(text)

print(re.findall(r"[^abc]+", "abz1cxy"))  # ['z1', 'xy']

s = "scatter catalog cat"
print(re.findall(r"\Bcat\B", s))  # 左右都在“单词内部”

s = "10kg 12g 8kg"
re.findall(r"\d+(?=kg)", s)   # ['10', '8']
# 解释:匹配的结果是数字本身;先行断言只检查“后面是不是 kg”。

s = "abc abc1 ab12 xyz"
re.findall(r"\b[a-zA-Z]+\b(?!\d)", s)   # ['abc', 'xyz']
# 解释:\b[a-zA-Z]+\b 是独立的字母词;(?!\d) 要求其后面不是数字。

s = "pay $12 and $3.5, not 7 or $x"
re.findall(r"(?<=\$)\d+(?:\.\d+)?", s)   # ['12', '3.5']
# 解释:只把数字取出来;(?<=\$) 确保数字前面是美元符号。

s = "visit example.com, mail a@foo.example.com"
re.findall(r"(?<!@)\bexample\.com\b", s)   # ['example.com']
# 解释:如果前面是 @(出现在邮箱里),就被排除。
-- 2025 年 9 月 24 日止 --

配套代码:vsme/learn-python



上一篇
Python 函数式编程
下一篇
人生第一次肠胃内镜检查