📊 第2章 搭建 Python 数据分析环境
📄 一句话概括

Python 是一门解释型语言:写好的代码不直接跑,先被翻成字节码,再由虚拟机逐条执行。 版本号第二位一变(3.12 到 3.13),第三方库就可能装不上——这是「版本」最实际的后果。 老的 print 语句在 3 里直接编译不过;7 / 2 在 2 里得 3,在 3 里得 3.5。

📝 本章和前面几章的关系

第 1 章讲的都是「为什么」;从这一章开始动手。 第 2 章一共八篇,全部围绕一件事:把环境搭起来,让代码能跑。 这一篇讲版本。看着简单,但「装错版本」是新手第一个大坑,而且它会在装库的时候才发作。

一、解释型是什么意思

编译型语言(C、Java)先整体翻成机器码,再运行。中间那步叫编译,产物能单独拿走。 Python 是解释型:源码先翻成「字节码」——一种中间形式,再交给虚拟机逐条执行。 字节码不直接变成机器码,所以 Python 比 C 慢。反过来,改一行不用等编译,改完就能跑。

代价换来的是迭代速度:试一个想法,从改到看到结果只要一秒。这对做数据分析很关键。

二、版本号的三段

Python 的版本号是三段:主版本.次版本.微版本,比如本篇跑在 3.13.14 上。

位置 含义 变了会怎样
第一段 3 主版本 语法大改,几乎不兼容(2 到 3 花了十年)
第二段 13 次版本 加新语法,第三方库要重新编译
第三段 14 微版本 只修 bug,随便升

关键在第二段。 3.13 出来了,3.12 编好的那些 C 扩展(numpy、pandas 都在内)用不了,得等它们发布 3.13 的版本。 这就是为什么「昨天还好好的,今天装个库说找不到」——多半是次版本号对不上。

三、两句老代码,两个坑

第一句:print "hello"。这在 Python 2 里完全合法,在 3 里编译不过,报错原文是 Missing parentheses in call to 'print'. Did you mean print(...)?——提示很直白,让加括号。 第二句:7 / 2。在 2 里得 3(整数相除向下取整),在 3 里得 3.5。

第二个坑更阴:代码不报错,就是算错。本该 3.5 的地方拿到 3,误差 14%,还看不出异常。 要整除得写 7 // 2,要余数写 7 % 2,这三个写法在 3 里分工清楚。

四、怎么确认自己在用哪个

命令行敲 python -V,或者代码里读 sys.version_info。 后者能直接比较,比如 sys.version_info >= (3, 8)。 不要切版本号字符串来比较:「3.9」和「3.13」按字符串比,3.9 反而大。 本机是 3.13.14,major=3。写脚本时如果要兼容老版本,用元组比较。

五、该装哪个

一句话:装 3.x 里最新的稳定版。不装 2.x,不装预览版(版本号带 a 或 b 的)。 2.x 在 2020 年停止维护,现在装它等于开局就踩坑,而且大部分库已经不支持。 预览版(比如 3.14a1)是给库的作者试兼容性用的,普通用户装了会遇到一堆装不上的包。

这一节的全部意义就一条:别在版本上省事。后面装的每个库都要跟它对齐。

六、动手 Demo:同一行代码,三个版本三种结果

先打出版本号,再试编译一句 Python 2 的 print,最后看除法的两个答案。 这段代码在 Python 2 和 3 里跑出来的结果不一样,正是本篇要讲的。

import sys

print("版本 %s" % sys.version.split()[0])
print("三段 %d.%d.%d" % sys.version_info[:3])

src = "print 'hello'"
try:
    compile(src, "<py2>", "exec")
    print("老的 print 语句:能编译")
except SyntaxError as e:
    print("老的 print 语句:编译失败")
    print("  报错:%s" % e.msg)

print("7 / 2  = %s" % (7 / 2))
print("7 // 2 = %d" % (7 // 2))
print("7 %% 2  = %d" % (7 % 2))

实跑输出:

--------------------------------------------------------------------
同一行代码,三个版本三种结果
--------------------------------------------------------------------

  ① 先看这台机器跑的是什么
  --------------------------------------------------------------------
  Python 的版本号是三段:主版本.次版本.微版本,这里是 3.13.14。
  完整串:3.13.14 (main, Jun 11 2026, 04:04:46) [MSC v.1944 64 bit (AMD64)]。
  教材用的是 3.x,所以本文所有代码按 Python 3 写。
  ! 版本号第二位一变(3.12 到 3.13),第三方库就可能装不上——这是「版本」最实际的含义。

  ② 老的 print 语句在 3 里根本编译不过
  --------------------------------------------------------------------
  「print 'hello'」这段代码:编译失败。
  报错原文:Missing parentheses in call to 'print'. Did you mean print(...)?
  原因是 Python 3 把 print 从「语句」改成了「函数」,必须写成 print("hello") 带括号。
  ! 这不是排版讲究。语句和函数是两种东西:函数能当参数传,语句不能。

  ③ 除法:同一个符号,两个答案
  --------------------------------------------------------------------
  在 Python 2 里,7 / 2 得 3——两个整数相除,结果向下取整。
  在 Python 3 里,7 / 2 得 3.5,整除要写 7 // 2 得 3。
  这一改让多少老代码算错了数:本该 3.5 的地方拿到了 3,误差不算小。

| 写法 | Python 2 | Python 3 |
|---|---|---|
| 7 / 2 | 3 | 3.5 |
| 7 // 2 | 3 | 3 |
| 7 % 2 | 1 | 1 |

  ! 所以看到「书上说结果是 3」先别急着改代码,先确认那本书是哪个年代写的。

  ④ 怎么查自己装的是哪个版本
  --------------------------------------------------------------------
  命令行里敲 python -V,或者代码里读 sys.version_info。
  本机是 3.13.14,major=3。
  ! 写脚本时判断版本用 sys.version_info >= (3, 8),不要去切版本号字符串。

  ⑤ 版本选哪个
  --------------------------------------------------------------------
  一句话:装 3.x 里最新的稳定版,不要装 2.x,也不要装预览版(带 a 或 b 的)。
  2.x 已经在 2020 年停止维护,现在装它等于开局就踩坑。
  ! 这一节的全部意义就一条:别在版本上省事。后面装的每个库都要跟它对齐。

compile 是内建函数,它只做「翻成字节码」这一步,不执行。用它来试语法最省事。 最后一行那个 %%:字符串里已经有 % 格式化,要打出一个百分号本身就得写两个。 这是本课后面反复出现的坑。

30 秒实验

  1. 把 7 / 2 换成 6 / 2,结果还是 3.0 吗?想想为什么。
  2. 查一下 sys.version_info 的完整内容,它一共几个字段?
  3. 想一想:为什么 Python 3 要把 print 从语句改成函数?函数比语句多了什么能力?

常见误区

  1. 按字符串比版本号:「3.9」比「3.13」大,这是字符串比较的结果,不是版本比较。
  2. 装预览版图新鲜:库还没适配,装十个包有八个失败。
  3. 以为改个 print 括号就迁移完了:除法、字符串编码、字典顺序都要查。
  4. 同时装好几个 Python 不管:PATH 里靠前的先被用上,你以为在用一个其实在用另一个。
自测三问(点开对答案) 1. 为什么次版本号(第二段)变化的影响比微版本大? —— 次版本会加新语法和新的 C 接口,第三方扩展要重新编译;微版本只修 bug,二进制兼容。 2. 7 / 2 在 Python 2 和 3 里分别得什么?为什么这是个危险的区别? —— 2 里得 3,3 里得 3.5。危险在于它不报错,只是悄悄算错,而且误差不小。 3. 判断版本该用什么写法? —— 用 sys.version_info >= (3, 8) 这样的元组比较,不要切字符串。

版本定了,接下来把它装上。 下一篇讲装在哪、装完系统怎么找到它——也就是 sys.executable 和 sys.path 这两件事。

相关笔记