上个月有个读者私信我,说他被一个bug折磨了整整一个下午。代码在公司Mac上跑得好好的,到家打开自己Windows笔记本,刚跑第一行就崩了:
UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 12: illegal multibyte sequence
他截图发给我的时候,屏幕上已经开了12个浏览器标签页,全是各种编码问题的解决方案。最后改了三处代码、在每个 open() 里手动加了 encoding='utf-8' 才解决。
类似的事情,几乎每个在Windows上入门Python的新手都遇到过。但好消息是:这些问题,在3个月后发布的 Python 3.15 里,很多要被彻底解决了。
根据Python官方的发布计划(PEP 745),Python 3.15 将于2026年10月正式发布。目前 beta 2 已经在6月发布,所有新功能已冻结,不再会有大的变动。这意味着我们现在就可以完整地预览新版本带来了什么。
我通读了所有PEP和What's New文档后,挑出了3个对编程新手影响最大的变化。这些变化可能不是3.15最硬核的更新——JIT编译器、frozendict、延迟导入那些更适合进阶开发者——但每一个都在直接解决新手真实踩过的坑。
先说结论:Python 3.15 的 PEP 686 将 UTF-8 设为所有 I/O 操作的默认编码。不管你在 Windows、Mac 还是 Linux 上,open() 打开文件、print() 输出、subprocess 运行命令,默认都用 UTF-8。
这听起来像个小改动,但对于在中文 Windows 环境下入门 Python 的新手来说,这可能是一年中最值的更新。
为什么?因为过去 Windows 的默认编码是 GBK(或 cp936),而 Mac 和 Linux 是 UTF-8。当你写了一段代码:
with open('data.txt', 'w') as f: f.write('你好,世界')
在 Mac 上完全没问题。但到 Windows 上,文件内容可能变成乱码。更糟的是读取别人分享的代码时:
with open('config.json') as f: config = json.load(f) # Windows上报错!
因为 config.json 里可能包含中文注释或中文字符串,而 open() 在 Windows 上默认用 GBK 去读 UTF-8 文件,直接崩。
过去解决这个问题,你得在每个 open() 后面加一句 encoding='utf-8':
with open('data.txt', 'w', encoding='utf-8') as f: f.write('你好,世界')
但新人往往不知道要加,或者忘了加,然后被报错折磨半天。我翻了一下过去半年收到的读者问题,编码问题牢牢占据新手安装后第一个报错的前三名。
Python 3.15 彻底改变了这一点。上面的代码在 Windows 上也能直接跑,不需要手动指定编码。
当然,如果你确实需要 GBK 编码(比如处理一些老项目的中文文件),也可以显式指定:
# 需要老编码时,手动指定with open('legacy.txt', encoding='gbk') as f: content = f.read()
如果整个项目都想回到老行为,也有命令行参数和环境变量:
# 禁用 UTF-8 模式python -X utf8=0 app.py# 或设置环境变量PYTHONUTF8=0 python app.py
但对大多数新手来说,你根本不需要关心这些——默认就是对的。
一个值得注意的细节:PEP 686 最早在 Python 3.12 就被讨论了,当时争议非常大,担心破坏向后兼容。经过三个版本的渐进式推进,终于在 3.15 彻底落地。这说明 Python 社区对新手的体验越来越重视了。
Python 3.14 引入了智能错误提示(比如告诉你是不是漏了冒号),而 3.15 把这个能力提升到了一个新高度:它能识别你跨语言的语法错误。
什么意思?很多编程新手同时在学 Python 和 JavaScript(前端后端都想搞),或者之前学过 Java/C++,切换到 Python 时会下意识写出其他语言的写法。
比如你想往列表里加一个元素,写成了 JavaScript 的 push:
my_list = [1, 2, 3]my_list.push(4)
在 Python 3.14 里你会看到:
AttributeError: 'list' object has no attribute 'push'
在 Python 3.15 里,报错变成了:
AttributeError: 'list' object has no attribute 'push'. Did you mean '.append()'?
Python 看出来了你在用 JavaScript 的 push,然后贴心地告诉你:在 Python 里你应该用 append。
再比如你从 Java 转过来,想把字符串转大写:
name = "hello"print(name.toUpperCase())
3.15 会提示你:
AttributeError: 'str' object has no attribute 'toUpperCase'. Did you mean '.upper()'?
甚至能识别你写的字典操作是否正确:
my_dict = {}my_dict.put('key', 'value')
3.15 告诉你:
AttributeError: 'dict' object has no attribute 'put'. Did you mean d['key'] = value?
这个功能对于同时在学多门语言的新手来说简直救命。你不需要记住每门语言的方法名差异,Python 会帮你纠错。
还有一个小细节:当你在元组上调用列表才有的方法时:
(1, 2, 3).append(4)
报错会变成:
AttributeError: 'tuple' object has no attribute 'append'. Did you mean to use a 'list' object?
它不仅告诉你做错了,还告诉你为什么会错——因为 tuple 是不可变的,如果你需要 append,应该用 list。
还有一个针对拼写错误的改进:
delattr(obj, 'nmae')
报错会友情提醒:
AttributeError: 'MyClass' object has no attribute 'nmae'. Did you mean 'name'?
这些改进虽然看起来只是多了一行提示,但对于还在努力记住语法的新手来说,这意味着少去搜索引擎里打5次字,少翻3个StackOverflow页面,多保住30分钟的学习热情。
PEP 798 允许在列表推导式、集合推导式、字典推导式和生成器表达式中使用 * 和 ** 解包操作符。
听起来有点抽象?直接看例子你就懂了。
假设你有一个嵌套列表,想把所有子列表的元素展平成一个列表:
lists = [[1, 2], [3, 4], [5]]
在 Python 3.14 及之前,你要么写一个双层循环的推导式:
result = [item for sublist in lists for item in sublist]# [1, 2, 3, 4, 5]
要么用 itertools:
from itertools import chainresult = list(chain.from_iterable(lists))
说实话,双层循环推导式的写法看着就绕——for sublist in lists for item in sublist 这个 for 的顺序跟直觉相反,很多新手要反应半天才能读懂。itertools 的方案倒是清晰,但需要额外导入模块,对小脚本来说有点杀鸡用牛刀。
Python 3.15 里,一行搞定:
result = [*L for L in lists]# [1, 2, 3, 4, 5]
一行,清晰,读起来就像自然语言:把每个子列表 L 解包后放进新列表。
字典推导式也支持解包,比如你想合并多个字典:
dicts = [{'a': 1}, {'b': 2}, {'a': 3}]merged = {**d for d in dicts}# {'a': 3, 'b': 2} 后面的键会覆盖前面的
集合推导式同样可以:
sets = [{1, 2}, {3, 4}, {2, 3}]result = {*s for s in sets}# {1, 2, 3, 4}
对于需要合并多个数据源的新手来说,这个语法比之前的方法直观太多。你不用去记双层 for 推导式的书写顺序,也不用纠结要不要为了一个简单的需求专门 import itertools。
而且这个语法对生成器表达式同样有效:
tuples = [(1, 2), (3, 4)]gen = (*t for t in tuples)result = list(gen)# [1, 2, 3, 4]
注意,这是一个完全向前兼容的新语法——你现有的代码不需要做任何改动。它只是在你想用的时候给你多了一个更简洁的选择。
说完这三个特性,你可能会问:我现在就想用,怎么装?
直接去 Python 官网(python.org)下载 Python 3.15.0b2 安装即可。但有一点非常重要:不要直接覆盖你现有的 Python 版本。你可以用 pyenv 或 conda 创建一个独立的环境来试用:
# Windows / Mac / Linux 都可用 pyenvpyenv install 3.15.0b2pyenv shell 3.15.0b2
Windows 用户如果不熟悉 pyenv,最简单的方式是下载官方安装包后,在安装过程中勾选 Install for me only 并选择一个独立的目录(比如 C:\Python315),不要覆盖系统已有的 Python。
另外提醒三个新手容易忽略的点:
第一,3.15 目前还在 beta 阶段,不建议直接用它来做正式项目或生产环境。但用来学习、测试新特性完全没问题。尤其是编码和报错体验这两项,你不需要改任何代码就能感受到提升。
第二,如果你在学习时用了 3.15 的新语法(比如推导式解包),要意识到这些代码在 3.14 及之前版本上跑不了。如果你在给公司写代码或者做开源贡献,记得先确认目标环境用的是哪个 Python 版本。
第三,正式版预计 2026 年 10 月发布,距离现在还有大约 3 个月。在此之前,各项功能不会有大变化,但性能调优和 bug 修复会在 RC 阶段继续进行。如果你在 beta 版里发现了 bug,可以去 Python 的 GitHub 仓库提 issue,这也是为开源社区做贡献的好机会。
Python 3.15 的整体更新其实远不止这三个。像 JIT 编译器性能提升、frozendict 内置类型、延迟导入、Tachyon 采样分析器,每一项都值得单独写一篇文章。
但我在挑选时特意避开了那些看起来厉害但对新手当下没什么用的特性,选了三个真正能减少新手日常痛苦的变化:不用再手动加 encoding='utf-8'、报错信息能猜中你写错了什么、嵌套列表一行搞定。它们分别对应了新手学 Python 时的三个高频痛点:环境跑不通、报错看不懂、代码写不简洁。
Python 的版本号从 2 到 3 用了 8 年,从 3.0 到 3.15 用了 18 年。每一次升级都在让这门语言变得更好用——不只是对老手来说更好用,对新手来说也在变得越来越友好。这可能就是 Python 能长期霸占编程语言排行榜前三的核心原因。
你目前在用哪个版本的 Python?有没有被编码问题或者推导式写法折磨过的经历?欢迎在评论区聊聊,我每条都会看。

长按或扫描下方二维码,免费获取 Python公开课和大佬打包整理的几百G的学习资料,内容包含但不限于Python电子书、教程、项目接单、源码等等
▲扫描二维码-免费领取
推荐阅读
Python代码写完了,然后呢?Git入门只需这6个命令,新手够用一整年
点击 阅读原文了解更多