news 2026/10/9 10:38:24

Python中常用功能的实现代码分享

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python中常用功能的实现代码分享

前言


这是一篇「常用代码片段」合集:日常写 Python 时反复要写的那几件事——交换变量、去重、扁平化、统计词频、合并字典、按值排序、成对遍历——都有比「你自己手写循环」更短、更清楚的现成写法。这些写法几乎都来自标准库,不需要装任何东西。


但要先立一个前提:「一行写完」不等于「更好」。有些一行写法确实更清晰(比如a, b = b, a交换变量),有些一行写法只是把复杂度藏起来,过两周自己都看不懂。本文挑的都是既短又好读的,并且会标注哪些依赖较新的 Python 版本、哪些只是实现细节不能依赖。


还有一个常见误解要提前说清:很多「技巧」依赖具体版本或实现。比如字典从Python 3.7 起才在语言层面保证保留插入顺序(3.6 是 CPython 的实现细节,官方不建议依赖),「用dict.fromkeys去重还能保序」正是建立在这条保证上的。再比如整数缓存(CPython 缓存-5到256)属于实现细节,跟这些日常片段无关但同样别依赖。本文示例以 Python 3.8 为基线,用到更高版本特性时会写明版本。


一、变量与序列的小操作


# 适用于 Python 3.8+
# 交换两个变量,不需要临时变量
a, b = 1, 2
a, b = b, a
print(a, b) # 2 1

# 连续赋值与解包
x = y = 0
first, *rest = [1, 2, 3, 4]
print(first, rest) # 1 [2, 3, 4]

# 链式比较,写起来和数学一样
age = 25
print(0 <= age < 100) # True

# 条件表达式(三元运算)
label = "成年" if age >= 18 else "未成年"
print(label) # 成年

解包里的*rest会把剩余元素收成一个列表,这是first, *rest = ...的固定语义。


二、去重与扁平化


保序去重是最常被写错的一个。用set去重会丢顺序,正确做法是用dict.fromkeys:


# 适用于 Python 3.7+(依赖字典保序)
seq = ["b", "a", "b", "c", "a"]
print(list(dict.fromkeys(seq))) # ['b', 'a', 'c']

# 反例:set 去重顺序不可控
print(list(set(seq))) # 顺序不保证,别依赖

dict.fromkeys(seq)用seq的元素当键建字典,键天然唯一且(3.7+)保序,再取出来就是去重后的序列。


把嵌套列表压平(flatten)有两种常见写法:


# 适用于 Python 3.8+
matrix = [[1, 2, 3], [4, 5], [6]]
flat = [x for row in matrix for x in row]
print(flat) # [1, 2, 3, 4, 5, 6]

from itertools import chain
flat2 = list(chain.from_iterable(matrix))
print(flat2) # [1, 2, 3, 4, 5, 6]

嵌套列表推导式的顺序是「先写外层 for,再写内层 for」,for row in matrix for x in row对应「先遍历行、再遍历行内元素」,写反了结果就不对。chain.from_iterable语义相同,但对任意层数的可迭代更通用。


反转序列注意原地与非原地的区别:


# 适用于 Python 3.8+
s = "abc"
print(s[::-1]) # 'cba' 返回新字符串

lst = [1, 2, 3]
print(list(reversed(lst))) # [3, 2, 1]
lst.reverse() # 原地反转,返回 None
print(lst) # [3, 2, 1]

三、字符串常用处理


# 适用于 Python 3.8+
# 判断回文
def is_palindrome(text):
cleaned = "".join(ch.lower() for ch in text if ch.isalnum())
return cleaned == cleaned[::-1]

print(is_palindrome("A man, a plan, a canal: Panama")) # True

# 统计词频
from collections import Counter

words = "the quick brown fox jumps over the lazy dog the".split()
counts = Counter(words)
print(counts.most_common(2)) # [('the', 3), ('quick', 1)]

# 字符串反转与大小写
print("hello".capitalize()) # 'Hello'
print("hello world".title()) # 'Hello World'

Counter是collections里的字典子类,专为计数设计;most_common(n)返回出现次数最多的前 n 项(按次数降序)。它的构造参数是任意可迭代对象。


四、字典常用处理


合并字典在 3.9 之前和之后写法不同:


# 适用于 Python 3.9+
d1 = {"a": 1, "b": 2}
d2 = {"b": 20, "c": 30}
print(d1 | d2) # {'a': 1, 'b': 20, 'c': 30} 右边覆盖左边

d1 |= d2 # 原地合并
print(d1) # {'a': 1, 'b': 20, 'c': 30}

# 适用于 Python 3.8 及更早:用字典解包
merged = {**d1, **d2}

安全取值用get而不是下标,下标取不存在的键会抛KeyError:


# 适用于 Python 3.8+
d = {"a": 1}
print(d.get("a")) # 1
print(d.get("z")) # None
print(d.get("z", 0)) # 0
print(d.setdefault("n", [])) # [] —— 键不存在时插入并返回默认值

按值排序、找最大值的键、反转字典:


# 适用于 Python 3.8+
scores = {"alice": 88, "bob": 95, "carol": 72}

print(sorted(scores.items(), key=lambda kv: kv[1], reverse=True))
# [('bob', 95), ('alice', 88), ('carol', 72)]

print(max(scores, key=scores.get)) # bob
print({v: k for k, v in scores.items()}) # 反转(值必须唯一才有意义)

sorted返回新列表;scores.items()是视图,本身不改动字典。


五、迭代与组合工具


# 适用于 Python 3.8+
# enumerate:同时拿到下标和值
for i, name in enumerate(["a", "b"], start=1):
print(i, name) # 1 a / 2 b

# zip:成对遍历,长度以短的为准
names = ["a", "b", "c"]
ages = [1, 2]
print(list(zip(names, ages))) # [('a', 1), ('b', 2)] 只到短的结束

zip默认在最短的可迭代对象耗尽时停止。想按最长的来、缺的用占位值补,用itertools.zip_longest:


# 适用于 Python 3.8+
from itertools import zip_longest

print(list(zip_longest([1, 2, 3], ["a"], fillvalue="-")))
# [(1, 'a'), (2, '-'), (3, '-')]

itertools.groupby用来按 key 分组,但它只对相邻的相同 key 分组,所以用之前必须先排序:


# 适用于 Python 3.8+
from itertools import groupby

data = [("fruit", "apple"), ("veg", "carrot"), ("fruit", "banana")]
data.sort(key=lambda p: p[0]) # 必须先排序
for key, group in groupby(data, key=lambda p: p[0]):
print(key, [g[1] for g in group])
# fruit ['apple', 'banana']
# veg ['carrot']

六、读取与小结


# 适用于 Python 3.8+
# 一行读入两个整数
a, b = map(int, input().split())

# 生成器表达式省内存(不是列表)
total = sum(x * x for x in range(1000))
print(total)

生成器表达式(x * x for x in ...)和列表推导式[x * x for x in ...]的区别是:前者惰性求值、不一次性建出整个列表,适合喂给sum、max、join这类会自己消费的函数。


常见坑点



  1. 用 set 做保序去重


❌list(set(data))顺序不可控,输出每次可能不同


✅list(dict.fromkeys(data))(3.7+ 保证保序)



  1. 嵌套推导式写反层序


❌[x for x in row for row in matrix]→NameError或结果错乱


✅[x for row in matrix for x in row],外层 for 写在前面



  1. 把 reverse() 的返回值接住


❌sorted_list = lst.reverse()得到None,lst反被原地改了


✅ 原地反用lst.reverse()且不接返回值;要新序列用reversed(lst)或lst[::-1]



  1. 下标取字典不存在的键


❌d["missing"]→KeyError


✅d.get("missing", 默认值),或在确需插入默认值时用setdefault



  1. 用 3.9 的|合并字典却跑在 3.8


❌d1 | d2在 3.8 上对字典是TypeError(3.9 才支持)


✅ 3.9 以下写{**d1, **d2}



  1. groupby 之前忘了排序


❌ 直接groupby(data, key=...),相同的 key 分散在多处,被分成了好几组


✅ 先data.sort(key=...)再groupby,它只合并相邻项



  1. 以为 zip 会对齐到最长


❌zip([1, 2, 3], ["a"])期望得到三个元素,实际只有[(1, 'a')]


✅ 要补齐用itertools.zip_longest(..., fillvalue=...)



  1. max(d, key=d.get)遇到并列时的迷惑


❌ 两个键的值一样大时,返回的是先遇到的那个,却以为有确定规则


✅ 并列时顺序取决于字典迭代顺序;需要确定的规则就自己写sorted后取第一个


总结




需求片段



交换变量a, b = b, a

保序去重list(dict.fromkeys(seq))

扁平化[x for row in m for x in row]或chain.from_iterable

反转s[::-1]、reversed(x)(不原地)

词频统计collections.Counter(it).most_common(n)

合并字典3.9+ 用 `d1 \

安全取值d.get(k, default)

按下标遍历enumerate(it, start=1)

成对遍历zip(a, b)(短的为准)

相邻分组groupby(必须先排序)



这些片段的价值不在于「短」,而在于它们背后都有清晰的语义:dict.fromkeys保序是字典保序保证的直接推论,zip短边截断、groupby只合相邻项是明确写进文档的行为。用之前先确认三件事——你的 Python 版本够不够、这段代码依赖的是语言保证还是实现细节、以及一行写法是不是真的比展开更好读。想清楚这三点,这些「常用功能」才会越用越顺,而不是变成下一个看不懂的历史代码。




版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 10:38:23

Python中嵌套类的实现

前言 嵌套类&#xff08;nested class&#xff09;指在另一个类的类体里再定义一个 class。它常被用来做命名空间分组、定义只服务于外层的辅助类型&#xff08;helper type&#xff09;&#xff0c;或者给 namedtuple 之类的东西找个归属。 需要先纠正一个普遍误解&#xff1a…

作者头像 李华
网站建设 2026/10/9 10:36:31

为什么要学Go语言?并发编程到云原生实战的底层逻辑

你问我为什么值得专门花时间了解Go语言&#xff1f;我直接说结论&#xff1a;因为整个软件行业的底层基础设施&#xff0c;正在全面转向Go。这不是某个小圈子的热闹&#xff0c;而是持续了很多年的结构性变化。最近两年我面试后端候选人&#xff0c;超过一半的简历里写着“熟悉…

作者头像 李华
网站建设 2026/10/9 10:35:37

神经网络本构模型嵌入Abaqus UMAT:粗网格多尺度仿真实现路径

简介&#xff1a;面向Abaqus高级用户与从事材料本构模型研究的人员&#xff0c;这套基于人工神经网络&#xff08;ANN&#xff09;的本构模型计算框架&#xff0c;重点解决网格粗化场景中复杂本构关系的描述与集成问题。框架包含数据生成器与ANN训练模块两大功能块&#xff0c;…

作者头像 李华
网站建设 2026/10/9 10:34:10

Harbor私有镜像仓库搭建与运维实战:基于Docker的完整指南

手里如果只跑着三五台机器&#xff0c;用 Docker Hub 或者阿里云镜像加速器就够了&#xff0c;但一旦服务器多起来、镜像有私有化要求&#xff0c;公共仓库的分发效率和安全性就有点绷不住。我自己的环境里&#xff0c;从最开始用 Docker Registry 裸跑&#xff0c;到后来换成 …

作者头像 李华
网站建设 2026/10/9 10:33:53

统一管理多个AI编程CLI:kshell配置、路由与上下文桥接实践

1. 为什么需要统一管理多个 AI 编程 CLI1.1 从单工具到多工具并存的现实困境过去一年里&#xff0c;AI 编程 CLI 工具的数量增长非常快。我自己的开发机上&#xff0c;前前后后装过至少六款不同的命令行 AI 编程助手&#xff0c;每一款都有自己的定位和擅长场景。有的擅长代码补…

作者头像 李华
网站建设 2026/10/9 10:33:43

Agentic AI工程化实战:从原理到生产落地

如果把 2024 年大模型行业的关键词定义为“长上下文 多模态”&#xff0c;那么 2025 年的关键词几乎可以确定只有一个&#xff1a;Agent&#xff0c;更准确地说&#xff0c;是 Agentic AI。它不再满足于“回答问题”&#xff0c;而是试图替人“完成任务”。 但有一个反差很值…

作者头像 李华