ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Mojo 运算符完全指南:从算术、位运算到优先级与赋值表达式的实战详解

2026/9/10 1:09:03 拓冰建站 浏览量
Mojo 运算符完全指南:从算术、位运算到优先级与赋值表达式的实战详解 Mojo 运算符完全指南从算术、位运算到优先级与赋值表达式的实战详解【免费下载链接】mojoThe Modular Platform (includes MAX Mojo)项目地址: https://gitcode.com/GitHub_Trending/mo/mojo本文以 Mojo 官方手册 Operators 章节为主线系统讲解 Mojo 语言中算术、比较、位运算、布尔逻辑、成员与身份、字符串、条件表达式、赋值运算符的语法与语义并结合仓库中的官方示例测试tests.mojo与标准库实现如Boolabletrait、isclose函数给出可验证的代码佐证。读完本文你将掌握 Mojo 与 Python 一脉相承又独具特色的运算符体系能够在自己的 Mojo 程序中正确选择运算符、理解优先级与结合性并规避浮点比较、符号位运算等常见陷阱。一、运算符在 Mojo 中的定位运算符Operators是作用于值的符号与关键字。它们让你用、、这样的运算符语法而非方法调用来完成加法、比较、位运算与布尔逻辑。Mojo 的运算符语法整体镜像 Python符号、优先级与结合性都遵循 Python 惯例因此如果你有 Python、C、Rust 等语言经验大部分行为会非常熟悉。不过有几处 Mojo 特有的细节需要特别注意布尔运算符使用单词and、or、not而不是、||这类符号三元条件表达式把条件放在中间x if cond else y而不是cond ? x : y脱字符^同时扮演按位异或与转移transfer符两个角色用于所有权与内存管理。这些细节正是 Mojo 作为Python 语法 系统级性能语言在设计上的独特取舍。二、算术运算符2.1 基础四则运算标准算术运算符与其他主流语言一致print(7 3) # 10, add print(7 - 3) # 4, subtract print(7 * 3) # 21, multiply幂运算使用两个星号**而不是脱字符^。如果你更喜欢函数形式可以调用pow(base, exponent)print(2 ** 8) # 256 (exponentiation)2.2 一元前缀运算符三个前缀运算符作用于单个值使用时将运算符紧贴值的左侧、不加空格-x取负如-7其中运算符是-表达式值是7x是无操作的身份运算符identity如7~x按位取反var a: Int8 -128; print(~a) # 127。仓库中的官方测试 tests.mojo 印证了这些行为def test_unary_symbols() raises: assert_equal(-7, -7) # -7 assert_equal(7, 7) # 7 var a: Int8 -128 assert_equal(~a, 127) # 127注意~a在Int8上得到127-128的二进制补码表示全 1 符号位加全 0 数值位按位取反后正好是127这直观体现了~对固定宽度整数类型的按位语义。2.3 除法与取余两个除法运算符的区别Mojo 有两种除法运算符对负数而言二者的差别至关重要var a -7 var b 4 print(a / b) # -1 (truncates toward zero, 向零截断) print(a // b) # -2 (rounds toward negative infinity, 向负无穷取整)需要向零截断truncation时用/需要向下取整floor division时用//。对浮点类型/执行标准除法//返回向下取整到最近整数的浮点数。取模运算符%返回余数并遵循如下恒等式a b * (a // b) (a % b)例如print(7 % 3) # 1 print(-7 % 4) # 1 print(7 % -4) # -1官方测试 tests.mojo 完整验证了这两组行为-7 / 4得到-1向零截断-7 // 4得到-2向下取整%的结果符号跟随除数方向-7 % 4 1而7 % -4 -1这与 Python 的取模语义一致。2.4 幂运算的结合性**是右结合的即从右往左分组print(2 ** 3 ** 2) # 512, same as 2 ** (3 ** 2)如果从左往左计算(2 ** 3) ** 2会得到64而实际结果是512这正是右结合的证据。幂运算是 Mojo 仅有的两个右结合运算符之一另一个是三目条件表达式if-else。2.5 矩阵乘法运算符执行矩阵乘法。如果你用过 NumPy对这个符号不会陌生。Mojo没有内置矩阵类型但任何实现了__matmul__()方法的类型都可以使用。这意味着是一个基于协议dunder 方法的运算符——你可以为自己的自定义矩阵、张量或线性代数容器类型实现__matmul__()从而获得与 NumPy 类似的矩阵乘法写法。三、比较运算符Mojo 提供六个比较运算符、!、、、、每个都返回Bool值print(10 5) # True print(10 10) # True print(10 ! 10) # False3.1 浮点比较不要用不要用相等运算符比较浮点值。微小的舍入误差会累积看起来相等的值往往并不相等from std.math import isclose var total: Float64 0.0 for _ in range(10): total 0.1 print(total 1.0) # False0.1无法在二进制浮点中精确表示累加十次后total与1.0存在微小偏差因此返回False。正确做法是使用isclose()做近似比较print(isclose(total, 1.0)) # True从源码看isclose定义在 math.mojo它是一个always_inline泛型函数支持 SIMD 向量输入并内置容差参数绝对容差atol: Float64 1e-08、相对容差rtol: Float64 1e-05、equal_nan: Bool False还支持对称Pythonmath.isclose风格与非对称NumPy 风格两种判据。默认的对称判据为|a - b| ≤ max(atol, rtol * max(|a|, |b|))官方测试 tests.mojo 印证了这一场景累加十个0.1后total 1.0为False而isclose(total, 1.0)为True。3.2 链式比较你可以在一个表达式里串联多个比较用于检查一个范围或一连串条件。每对比较从左到右依次求值var x 5 print(1 x 10) # True, 1 x and x 10 print(1 x 3) # False, 1 x and x 3 print(1 x 5 9) # True, 1 x and x 5 and 5 9表达式a b c等价于(a b) and (b c)。中间值只求值一次而不是两次——当中间值来自函数调用时这一点尤为重要var short_item_list: List[Int] [1, 2, 3, 4, 5] var ok 0 len(short_item_list) 10 print(ok) # True比较、成员membership与身份identity运算符共享同一优先级因此可以在同一条链中混用。例如下面的假设示例5 ! a b in c is d它等价于(5 ! a) and (a b) and (b in c) and (c is d)链式比较的测试在 tests.mojo 中完整覆盖包括1 x 5 9与0 len(short_item_list) 10两个用例。四、位运算位运算符在整数类型的比特层面工作让你直接检视与操纵单个位。AND保留两个操作数中都置位的比特OR|保留任一操作数置位的比特XOR^保留两者不同的比特var flags: UInt8 0b0000_0101 var mask: UInt8 0b0000_0011 print(flags mask) # 1 (only bit 0 set in both) print(flags | mask) # 7 (bits 0, 1, and 2) print(flags ^ mask) # 6 (bits 1 and 2 differ)左移与右移把比特移动给定数量的位置。左移 n 位等价于乘以 2^n右移 n 位等价于除以 2^nprint(1 4) # 16 print(16 2) # 4 print(-16 2) # -4注意-16 2得到-4对有符号整数右移是算术右移会保留符号位等价于向负无穷方向的除法。位运算符的优先级从紧到松依次是取反~最紧→ 移位 →→^→|最松。如果分组不直观就用括号。⚠️注意^的双重身份Mojo 用^同时表示按位异或与转移运算符。在含义可能产生歧义的表达式中Mojo 将其视为异或。例如x^1解析为(x ^ (1))而不是((x^) 1)。这是从 operators.mdx 明确说明的语言规则。官方测试 tests.mojo 对位运算与移位做了逐一验证0b0101 0b0011 1、|得7、^得6以及1 4 16、16 2 4、-16 2 -4。五、布尔逻辑Mojo 用单词而非、||表示布尔运算符读起来像自然语言print(True and False) # False print(True or False) # True print(not True) # False5.1 短路求值and与or在结果一旦确定时立即停止求值。对and若左侧为假右侧不再求值对or若左侧为真右侧被跳过def always_true() - Bool: print(called) return True # The string called never prints because the left side # of and is already False: print(False and always_true()) # False这个特性在右侧有副作用或计算代价高昂时非常有用。官方测试 tests.mojo 注释中特别指出called 永远不会打印因为and的左侧已经是False。不过也需要注意由于 Mojo 会在编译期对常量条件导致的不可达代码给出诊断这类短路场景在测试中只能以注释形式呈现见 tests.mojo 中True and False、True or False被标注为 Not testable 的原因。5.2 真值判断Truthiness符合Boolabletrait 的类型拥有真值可以直接用于布尔表达式与if条件。规则可预测零、空字符串、空集合与None为假其余为真。var name Mojo if name: print(Name is set)从标准库源码看Boolabletrait 定义在 bool.mojo它要求类型实现__bool__()方法描述为可以被显式转换为Bool或在if/while条件中被求值为布尔表达式的类型。自定义类型只需实现__bool__()即可获得真值语义struct Foo(Boolable): var val: Bool def __bool__(self) - Bool: return self.val六、成员与身份运算符6.1in与not inin检查集合是否包含某个值var colors: List[String] [red, green, blue] print(red in colors) # True print(yellow not in colors) # True它也适用于字符串的子串检查var food peanut butter if nut in food: print(Contains a nut) # prints6.2is与is not身份运算符检查两个值是否引用同一个对象而不仅仅是值相等。最常见的用途是检查Optional值是否为Nonevar opt: Optional[Int] None if opt is None: print(No value) # prints opt 42 if opt is not None: print(Has a value) # prints测试 tests.mojo 覆盖了in/not in列表与子串以及is None/is not NoneOptional[Int]全部用例。七、字符串运算符字符串支持用拼接、用*重复var greeting Hello Mojo print(greeting) # Hello Mojo print(ha * 3) # hahaha print( * 40) # a line of 40 equals signs性能提示当需要由多个值拼接字符串时多参数版本的String()构造器比链式更高效var result String(Point (, x, , , y, )) # or var result String(tPoint({x}, {y}))字符串按字典序比较大写字母排在小写字母之前因为 ASCII 码中大写字母更小print(Zebra ant) # True print(bird bird) # True测试 tests.mojo 验证了拼接Hello Mojo、重复ha * 3、 * 5以及字典序比较apple banana、Zebra ant等行为。八、条件表达式三目运算符Mojo 使用if-else作为条件表达式而不是? :。条件位于中间var score 80 var result pass if score 65 else fail print(result) # pass这种形式在任何表达式合法的位置都可以使用包括函数参数def greet(name: String): print(Hello,, name) greet(Sami if True else Cass) # Hello, Sami与幂运算一样链式三目表达式是右结合的从右往左分组这可能难以阅读var value 50 var label ( low if value 10 else high if value 100 else mid ) print(label) # mid测试 tests.mojo 覆盖了简单条件表达式score 65得pass与链式三目value为50、0、150时分别得到mid、low、high的全部分支。九、赋值运算符9.1 原地赋值In-place assignment大多数二元运算符都有复合赋值形式、-、*、/、//、%、**、、、|、^、、。它们更新左侧的值而不是创建新值var count 0 count 1 count 1 print(count) # 2 var flags: UInt8 0b0000_0001 flags | 0b0000_0100 print(flags) # 5 (bits 0 and 2 set)对于在堆上存储数据的类型原地运算符可以避免分配中间值。但一个类型必须显式实现其原地方法因此并非所有支持的类型都支持。测试 tests.mojo 用UInt8位标志完整演练了|、、^的原地更新语义。9.2 海象运算符:赋值表达式海象运算符:正式名称为赋值表达式在表达式内部完成赋值被赋的值成为该表达式的结果while (var name : input(Name or return: )): print(Hello,, name)上例中空字符串为假因此按 Return 而不输入任何文本即可终止循环非空字符串为真继续循环。input()是 raising 函数因此必须从 raising 函数中调用它或用try处理其错误。十、运算符优先级总表当一个表达式混合多种运算符时优先级决定谁先执行。从最紧到最松的完整次序为调用与属性访问calls and attribute access幂运算**一元前缀运算符-、、~、not算术先乘除*///%后加减-移位位运算先于^^先于|比较、成员与身份!inis等同一层布尔逻辑not先于and先于or条件表达式if-else海象运算符:有疑问时就加括号——括号在运行时零成本却能让你的意图在编写与后续维护时都一目了然# Clear without thinking about precedence var ready (age 18) and (score threshold)最后一条重要的语言规则赋值运算符、、-等是语句而非表达式不能把它们混入表达式之中。十一、示例与测试如何运行官方运算符示例本仓库在 Mojo/docs/site/code/manual/operators 目录下提供了与本文配套的代码示例与测试该目录下每个.mojo文件都是一个独立的 Mojo 应用程序tests.mojo 把 operators.mdx 中的全部可测试代码示例改写为assert_equal断言共覆盖算术、幂运算、一元符号、除法与取余、模运算、右结合幂、比较、浮点比较、链式比较、位运算、移位、布尔逻辑、短路、真值、成员、子串、身份、字符串拼接与重复、字符串比较、条件表达式、链式三目与原地赋值等二十余个测试函数全部在main()中顺序执行BUILD.bazel 使用 Bazel 的mojo_binary为每个.mojo文件生成同名可执行目标依赖mojo//:std并为每个二进制生成带_test后缀的modular_run_binary_test测试目标size small这意味着你可以用标准 Bazel 流程直接运行这些官方用例bazel test //Mojo/docs/site/code/manual/operators:tests_test如果你想快速验证某个运算符行为也可以直接运行对应二进制bazel run //Mojo/docs/site/code/manual/operators:tests值得留意的是测试文件头部注释说明了哪些示例被跳过及其原因假设性链式表达式、String()构造器涉及未定义变量、海象运算符需要input()交互、涉及未定义变量的优先级示例以及矩阵乘法Mojo 无内置矩阵类型。这些不可测试的示例正好从侧面印证了前文讨论的协议化设计、:的交互性以及链式比较的假设场景。总结Mojo 的运算符体系以 Python 语义为骨架融合了系统编程语言对位级操作、所有权转移与性能的关注。掌握这一体系的关键可以概括为四点符号约定幂用**、布尔用单词、三目用if-else、^兼作异或与转移符——这些是与 Python 或 C 系语言最主要的差异除法与取余语义/向零截断、//向下取整、%满足恒等式a b * (a // b) (a % b)对负数尤其要小心浮点比较永远用isclose()而非其容差参数atol、rtol已在标准库中提供默认值优先级与结合性只有**与三目表达式是右结合的其余遵循从紧到松的明确次序不确定时优先使用括号。文中所涉及的运算符行为均有 operators.mdx 官方手册、tests.mojo 可运行测试以及 bool.mojo 与 math.mojo 等标准库源码作为依据你可以直接在仓库中逐一验证。【免费下载链接】mojoThe Modular Platform (includes MAX Mojo)项目地址: https://gitcode.com/GitHub_Trending/mo/mojo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考