Julia 学习笔记——补充. 与 Python 和 MATLAB 的差异整理
这一篇把 Julia 与 Python、MATLAB 的主要差异集中整理一下,方便在系统看各个专题之前先有个整体印象。
先说明几点:
- 下文默认读者已经熟悉 Python 和 MATLAB;
- 默认以 Julia 1.12 系列为准;
- 这里只做迁移视角下的差异整理,不追求把所有细节一次性讲完;
- 真正的语法和行为细节,仍然以后面各专题笔记为主。
概述
如果只用一句话概括,Julia 大致可以理解为:
- 语法观感上吸收了 Python、MATLAB、Fortran 等科学计算语言的很多习惯;
- 执行模型上又明显更接近带 JIT 的编译型语言;
- 语言设计中心不是 class,而是数组、数值计算、泛型函数和多重分派。
因此,从 Python 或 MATLAB 迁移到 Julia 时,真正需要适应的往往不是“语法会不会写”,而是下面这些更底层的习惯:
- 语言默认鼓励什么样的代码组织方式;
- 哪些直觉来自 Python,哪些来自 MATLAB,而 Julia 恰好都不完全一样;
- 编译、类型推断和方法分派会如何反过来影响日常写法。
整体定位
和 Python 相比,Julia 最明显的差异在于:它并不是先把语言做成通用脚本语言,再靠大量 C/C++ 扩展补上数值性能,而是一开始就把“高性能科学计算”当作核心目标。
- Python 的科学计算主力通常来自 Numpy、SciPy、PyTorch 这类扩展库;
- Julia 则希望大量数值代码直接写在语言本身中,也能获得不错的性能;
- Python 中很多“为了绕开解释器开销”的技巧,在 Julia 里未必仍然是必要的。
和 MATLAB 相比,Julia 也明显不是“开源版 MATLAB”。
MATLAB 的强项在于:
- 数值计算语法成熟;
- 工具箱生态稳定;
- 工作区、脚本、矩阵心智模型非常统一。
Julia 更像:
- 继承了科学计算语言的书写便利;
- 但抛掉了不少 MATLAB 的历史包袱;
- 同时引入了更完整的模块系统、类型系统和包管理。
如果再把视野放宽一点,Julia 的整体设计还能看出一些和其他语言的亲缘关系:
- 在科学计算定位上,它和 MATLAB、Fortran、R 属于同一大类,都是把数值计算当成核心任务来设计;
- 在底层执行模型上,它又明显比 Python、MATLAB 更接近带 JIT 的现代编译型路线,这一点更容易让人联想到 JVM、LLVM 体系中的语言;
- 在泛型函数和分派机制上,它和 C++ 的重载、模板思维有一定相通之处,但 Julia 把这套能力直接做成了语言运行时的常规机制;
- 在 Unicode 标识符、数学记号、广播和点语法这些地方,它又带有一种很强的“让代码尽量接近公式”的设计倾向,这在传统通用编程语言里并不常见。
语法和数据模型
在代码块结构上:
- Julia 使用
end结束代码块; - MATLAB 也大量使用
end; - Python 则依赖缩进。
在一些零碎但高频的语法点上:
- Julia 使用
#注释,和 Python 一样,而 MATLAB 使用%; - Julia 使用
elseif,MATLAB 也使用elseif,Python 使用elif; - Julia 语句通常不需要
;,但在 REPL 中加;可以抑制结果显示;MATLAB 中;的存在感更强。
在数组和索引上,Julia 同时像 Python/Numpy,又像 MATLAB:
- Julia 从
1开始索引,这点和 MATLAB 一样、和 Python 不同; - Julia 使用
A[i, j]访问元素,这点和 Numpy 一样、和 MATLAB 不同; - Julia 默认列优先,这点和 MATLAB/Fortran 更接近;
- Julia 有真正的一维数组
Vector,而 MATLAB 更偏向“万物皆矩阵”; - Julia 切片范围是闭区间,普通切片默认返回拷贝而不是视图,这一点和 Numpy 的常见直觉差异很大。
在线性代数和逐元素运算上,Julia 又明显更像 MATLAB:
*表示矩阵乘法;.*表示逐元素乘法;^表示幂;.^表示逐元素幂。
这和 MATLAB 很接近,而 Python / Numpy 中 * 默认是逐元素乘法,@ 才是矩阵乘法。
在基本数据类型上,Julia 的风格通常比 Python 和 MATLAB 都更“明确”:
- Julia 默认整数通常是固定位数整数,而 Python 整数是任意精度,MATLAB 默认数值大多先落在浮点数上;
- Julia 用
nothing表示空值,Python 用None,MATLAB 里很多类似语义场景会写成[]; - Julia 单引号表示字符、双引号表示字符串,这和 Python 不同;
- Julia 用
im表示虚数单位,而 MATLAB 常见写法是i/j,Python 使用j。
如果从更宽泛的语言设计角度看,这里也能看到一些额外的对比:
- Julia 在数值字面量、复数、有理数、特殊浮点值等方面的支持,比很多通用脚本语言更加“数学化”;
- 但它又不像 MATLAB 那样几乎把所有默认数值都压到浮点数一条线上,而是保留了更清晰、更适合编译优化的类型区分;
- 在字符串和值类型处理上,Julia 又比 Python 更强调“不同概念就是不同类型”,这点反而更接近很多静态语言。
函数、类型和作用域
Julia 表面上和 Python 一样,把函数当作一等公民:函数可以赋值、传参、返回。但 Julia 的函数体系远不只是“把 def 换成 function”。
最关键的区别是:
- Julia 允许最后一个表达式自动作为返回值;
- Julia 的默认参数是在每次调用时按需计算,而 Python 的默认值是在定义时计算一次;
- Julia 对关键字参数和位置参数的区分比 Python 更严格;
- Julia 的同名函数可以对应多组不同的方法实现,调用时再根据参数类型选择具体方法。
这最后一点,就是 Julia 最有代表性的多重分派机制。Python 中类似行为通常要靠动态判断、默认参数、*args/**kwargs 或手工分支来模拟;MATLAB 也有某些重载体验,但远没有 Julia 这样把它放在语言中心。
在类型系统上,Julia 也明显比 Python 和 MATLAB 更强势:
- Python 是动态类型,但很多时候并不强调显式类型层次;
- MATLAB 在日常数值代码里通常也不强调类型系统;
- Julia 则把抽象类型、具体类型、参数化类型、方法分派和类型推断都放在非常核心的位置。
这带来的直接影响是:在 Julia 中,写法是否利于类型稳定和编译器推断,会比 Python 和 MATLAB 中重要得多。
如果把它和其他语言放在一起看,会更容易理解 Julia 的位置:
- 和 Python、MATLAB 这类动态语言相比,Julia 的类型系统明显更强,也更直接参与性能;
- 和 Java、C# 这类以 class 为中心的语言相比,Julia 的重心又不在类层次,而在函数和方法;
- 和 C++ 相比,Julia 也做泛型和重载,但它不是把复杂度主要压在编译期模板机制上,而是通过运行时分派和特化编译来完成;
- 和传统函数式语言相比,Julia 虽然函数地位很高,但它的目标并不是纯函数式,而是面向数值计算的多范式混合设计。
在作用域和变量语义上,Julia 也有自己的一套风格:
- 比 MATLAB 更规范完整;
- 某些地方和 Python 相似;
- 但因为 soft scope / hard scope、REPL 与脚本行为差异等问题,又不能简单地按 Python 直觉套用。
另外,虽然三种语言都不太鼓励滥用全局变量,但 Julia 对全局变量尤其敏感,因为它不只是代码组织问题,还会直接影响性能推断和编译优化。
工程组织和执行模型
在模块和包管理上,Julia 也不完全像 Python,更不像 MATLAB。
和 Python 相比,一个很重要的不同点是:
- Python 常常是“一个文件天然就是一个模块”;
- Julia 更常见的是“一个主模块 + 若干
include(...)文件”的组织方式。
和 MATLAB 相比,Julia 的模块系统、包系统和项目环境又明显更现代:
- 有清晰的命名空间概念;
- 有统一的
Pkg包管理; - 有
Project.toml/Manifest.toml这种项目环境描述; - 环境更像依赖解析上下文,而不是简单的工作区或脚本目录。
最后是执行模型和性能,这也是 Julia 和 Python / MATLAB 差异最大的地方之一。
Python 和 MATLAB 默认都更偏解释器工作流,而 Julia 明显更依赖 JIT:
- 函数第一次遇到某组参数类型时,可能触发编译;
- 后续同类调用才更快;
- 因此“第一次慢、后面快”是正常现象。
这也会直接改变很多性能经验。尤其是在向量化这件事上:
- 在 Python / MATLAB 中,向量化通常既是写法习惯,也是性能手段;
- 但在 Julia 中,
for循环本身通常已经足够快; - 向量化更多是表达问题,而不是默认的性能捷径;
- 如果写得不合适,反而可能引入额外分配。
所以从 Python 或 MATLAB 迁移到 Julia 时,很多原本“理所当然”的经验其实都需要重新判断。
如果进一步把它和 C/C++、Fortran 这类传统高性能语言对比,那么 Julia 的特点会更清楚:
- 它不像 C/C++ 那样把编译期和运行期分得非常开;
- 也不像 Fortran 那样在数值性能上高度稳定,但语言抽象手段相对保守;
- Julia 想做的是在高层抽象和高性能之间取得更直接的统一,这也是为什么它一方面很像脚本语言,另一方面又始终带着明显的编译器存在感。
小结
从 Python / MATLAB 迁移到 Julia,最早需要改掉的几个直觉大概就是这些:Julia 的中心不是 class,而是数组、泛型函数和多重分派;语法表面上像 Python 和 MATLAB 的混合体,但执行模型更接近带 JIT 的编译型语言;Python 和 MATLAB 里很多为了迁就解释器或工作区形成的经验,在 Julia 里都要重新判断。
