Mojo 函数与错误处理
本篇覆盖:函数定义、类型化签名、可选参数、错误处理(raises / try-except)、docstring、闭包。
一、函数定义:def 一统天下
Mojo 1.0 里函数统一用 def 定义(旧版的 fn 关键字已淡出主线)。参数和返回值必须标注类型:
mojo
def greet(name: String) -> String:
return "Hello, " + name + "!"
def main():
print(greet("Mojo")) # Hello, Mojo!没有返回值的函数省略箭头:
mojo
def log(msg: String):
print("[INFO]", msg)一个完整的例子
mojo
def calculate_average(temps: List[Float64]) -> Float64:
var total = 0.0
for temp in temps:
total += temp
return total / Float64(len(temps))
def main():
var temps: List[Float64] = [20.5, 22.3, 19.8, 25.1]
print(calculate_average(temps)) # 21.925二、可选参数与关键字参数
mojo
def power(base: Float64, exp: Int = 2) -> Float64:
var result = 1.0
for _ in range(exp):
result *= base
return result
def main():
print(power(3.0)) # 9.0,使用默认值
print(power(2.0, 10)) # 1024.0,位置传参
print(power(base=2.0, exp=3)) # 8.0,关键字传参三、错误处理:raises + try-except
这是 Mojo 和 Python 差异最大的地方之一。可能抛出错误的函数必须声明 raises,编译器据此检查调用链:
mojo
def calculate_average(temps: List[Float64]) raises -> Float64:
if len(temps) == 0:
raise Error("没有温度数据")
var total = 0.0
for temp in temps:
total += temp
return total / Float64(len(temps))调用方必须处理:
mojo
def main():
var temps: List[Float64] = []
try:
var avg = calculate_average(temps)
print(avg)
except e:
print("出错:", e) # 出错: 没有温度数据这个设计的好处:
- 错误传播路径在函数签名上显式可见——不进函数体就能知道它会不会炸
- 编译器保证「能抛错的函数一定被 try 包住」,不会出现 Python 那种运行时才爆的裸异常
raises函数对编译器还是性能提示——无 raises 的函数不会生成异常处理路径
自定义错误信息
Error 接受字符串描述,异常对象可直接打印:
mojo
raise Error(t"参数非法: 期望正数, 实际 {x}")四、docstring
三引号字符串即 docstring,mojo doc 命令可据此生成 API 文档:
mojo
def calc_bmi(weight: Float64, height: Float64) -> Float64:
"""计算 BMI 指数。
Args:
weight: 体重(千克)
height: 身高(米)
Returns:
BMI 值 = weight / height²
"""
return weight / (height * height)五、闭包与 lambda
Mojo 支持现代的 lambda 表达式(比旧版 @parameter 闭包语法更简洁):
mojo
def main():
# lambda 表达式
var double = lambda(x: Int) -> Int: x * 2
print(double(21)) # 42
# 闭包:捕获外部变量
var factor = 10
var scaled = lambda(x: Int) -> Int: x * factor
print(scaled(5)) # 50闭包细节(捕获方式、move 语义)会在需要时再深入,日常使用先记住这个形态。
六、函数是「一等性能公民」
两个值得知道的底层事实:
- 小类型走寄存器:
Int、Float64、SIMD等小类型传参永远走 CPU 寄存器,没有堆分配——这是 Mojo 数值代码快的重要原因 - 编译器可内联与专门化:配合编译期参数(第七篇),同一个函数会为不同类型/常量生成专门版本
七、小结
| Python | Mojo 1.0 |
|---|---|
随时 raise Exception | 必须先声明 raises |
| 调用方可不处理 | 编译器强制 try 或继续上抛 |
lambda x: x*2 | lambda(x: Int) -> Int: x * 2 |
| docstring | docstring + mojo doc 生成文档 |
| 默认参数/关键字参数 | 一致支持 |
下一篇:struct 结构体与生命周期。