Python技术迷

如果不懂Numpy,请别说自己是Python程序员

昨晚加班到十点多,在工位上喝着冷掉的咖啡,突然听到隔壁工位的小李跟人吹牛:“我写 Python 好几年了,NumPy 也就用过几次,不重要。”我当时差点没忍住笑出来。说真的,如果你还在说“NumPy 不重要”,那基本上就是在自我暴露:你对 Python 的理解还停留在“脚本语言”层面。今天我就想聊聊,为什么不懂 NumPy,就别急着喊自己是 Python 程序员。

Python 的灵魂之一:NumPy

Python 火起来,一半是因为生态,一半是因为科学计算。你看,NumPy 就是 Python 科学计算的基石。所有高阶库,像 Pandas、TensorFlow、PyTorch,甚至 OpenCV,都在底层依赖 NumPy。它其实就是 Python 和 C 语言的桥梁,把数学运算跑到 C 层实现,速度快得飞起。

比如你平时写个 for 循环,求个平方和,可能还洋洋自得,写成这样:

nums = [i for i in range(1, 1000000)]
s = 0
for n in nums:
    s += n * n
print(s)

这玩意儿跑下来要几百毫秒。但换成 NumPy,瞬间不一样:

import numpy as np

arr = np.arange(1, 1000000)
s = np.sum(arr ** 2)
print(s)

时间差别不是一点点,可能快几十倍。你要说你是 Python 程序员,却还用循环去写这种东西,那就好比开着电动车还在用脚蹬,累不累?

你以为的“数组”和真正的 ndarray

小白刚开始接触 NumPy,会觉得“哎呀不就是个数组库嘛”,其实完全不是一个量级的。Python 自带的 list,底层是链表式存储,每个元素都是对象引用,占空间大,查找效率低。NumPy 的 ndarray,底层就是一块连续的内存,直接存储数值,和 C 语言数组一样紧凑。

这也是为什么 NumPy 支持所谓的“广播机制”。比如一个二维矩阵加一个标量,你不用写循环,它直接帮你扩展计算:

a = np.array([[1, 2, 3],
              [4, 5, 6]])
b = 10
print(a + b)

输出就是:

[[11 12 13]
 [14 15 16]]

要是用 list,你得写两层循环手动加,这效率差距就一眼能看出来。

为什么工程里少不了它

说个实际场景。前两天我在写一个日志分析工具,要统计日志里的响应时间分布。普通写法,先用正则抽数据,再 list 存储,再算平均值、方差。写了几十行代码。后来一想,这不就是 NumPy 的强项吗?换成 NumPy:

import numpy as np

times = np.array([12, 15, 20, 11, 17, 19, 21])
print("平均:", np.mean(times))
print("方差:", np.var(times))
print("中位数:", np.median(times))

三行搞定,结果比我写的还准确。再配合 matplotlib 画图,立马就能出个直方图。

你要是不会 NumPy,写数据处理代码就是跟自己过不去。别忘了,数据分析、机器学习、图像处理,甚至金融建模,全都绕不开 NumPy。

初学者常掉的坑

这几年带新人,我发现有几个典型的误区:

  1. 当 list 用:很多人把 NumPy array 当 list 去 append、pop,结果发现报错。其实 array 的大小是固定的,你要加元素得用 np.concatenate 或者预分配。

  2. 没搞懂广播:比如一个 (3,1) 的矩阵加一个 (1,3) 的矩阵,结果直接得到 (3,3),不少人一脸懵。其实这就是 NumPy 自动扩展维度的规则。

  3. 混用 list 和 ndarray:有的人 arr = np.array([1, 2, 3]),后面还写 arr + [4, 5, 6],结果出来的结果和预期不符。因为 list 运算和 ndarray 运算规则完全不同。

工程级的威力

我上个月在做一个小型推荐系统实验,需要处理几百万条用户行为记录。如果不用 NumPy,光循环就能把人卡死。后来我用 np.dot 写了矩阵乘法,几行代码就把协同过滤的核心搞定了。

# 用户-物品矩阵
user_item = np.array([[5, 3, 0],
                      [4, 0, 0],
                      [1, 1, 0],
                      [0, 0, 5],
                      [0, 0, 4]])

# 物品相似度矩阵
similarity = np.dot(user_item.T, user_item)

print(similarity)

这个结果就能直接拿去算推荐分数,效率高到爆炸。要是手写三层循环,你估计写完都下班了。

NumPy 是 Python 程序员的底线

我经常说一句话:NumPy 是 Python 程序员的底线。为什么?因为它不仅仅是个库,它是整个 Python 数据计算生态的根基。不会 NumPy,就像 Java 程序员不会集合框架,C++ 程序员不会 STL,几乎寸步难行。

而且 NumPy 的 API 并不难学,学会几个核心函数:array、reshape、sum、mean、dot、where,再加上切片和广播,就能覆盖 80% 的场景。剩下的东西,等你真遇到了再查文档就好。

写这篇的时候,我脑子里一直回荡着小李那句“NumPy 不重要”。其实这不是小李一个人的问题,很多人写 Python 写了几年,却一直停留在写脚本、写接口的层面。你要真想说自己是 Python 程序员,就得把 NumPy 至少吃个七八分。

不然,下次别人问你:“数据处理用什么写?”你要是还在 list 里 while 循环,那我劝你还是先把简历上的“精通 Python”删了,免得面试官笑出声。

写个扩展练习题:用 NumPy 模拟 100 万个随机投骰子的结果,统计每个点数出现的概率。你写出来,才算是真正踏进 NumPy 的大门。

import numpy as np

# 模拟 100 万次投骰子
rolls = np.random.randint(1, 7, size=1000000)

# 统计频率
counts = np.bincount(rolls)[1:]  # 忽略0
probs = counts / rolls.size

print("点数出现的概率:", probs)

这就是 Python 的真正魅力:简洁、强大、优雅。不会 NumPy,真的别急着喊自己是 Python 程序员。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领