飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • 第1章 Python简介

    • Python是什么
    • 安装与运行
    • 交互式解释器
    • 注释与编码规范
  • 第2章 变量与数据类型

    • 变量与对象
    • 整数 int
    • 浮点数 float
    • 复数 complex
    • 布尔值 bool
    • 字符串 str
    • 空值 None
    • 类型转换
  • 第3章 运算符与表达式

    • 算术运算符
    • 比较运算符
    • 赋值运算符
    • 逻辑运算符
    • 位运算符
    • 身份与成员运算符
    • 海象运算符
    • 运算符优先级
  • 第4章 流程控制

    • if 语句
    • if-else 语句
    • if-elif-else 语句
    • match-case 语句
    • 条件表达式(三元运算符)
    • while 循环
    • for 循环
    • range 函数
    • break 与 continue
    • 循环的 else 子句
    • pass 语句
  • 第5章 数据结构

    • 列表创建与索引
    • 列表方法
    • 列表推导式
    • 元组
    • 序列解包
    • 集合
    • 字典创建与访问
    • 字典方法
    • 字典推导式
    • range 对象
  • 第6章 函数

    • 定义函数
    • 位置参数与关键字参数
    • 默认参数
    • 可变参数
    • 解包实参
    • 函数返回值
    • lambda 表达式
    • 文档字符串与注解
    • 作用域与命名空间
    • global 与 nonlocal
  • 第7章 模块与包

    • 模块导入
    • 模块搜索路径
    • 包与相对导入
    • 标准库概览
  • 第8章 文件与输入输出

    • 文件读写
    • 上下文管理器
    • 字符串格式化
    • JSON 与 CSV
  • 第9章 面向对象

    • 类与对象
    • 方法
    • 实例变量与类变量
    • 私有变量
    • 继承
    • 多重继承
    • 魔术方法
    • 属性装饰器
    • 数据类 dataclass
  • 第10章 异常处理

    • 语法错误与异常
    • try-except
    • 异常链与 raise
    • 清理操作
    • 自定义异常
  • 第11章 迭代器与生成器

    • 迭代器协议
    • 生成器
    • 生成器表达式
    • 迭代工具
  • 第12章 高级特性

    • 装饰器
    • 函数式编程
  • 第13章 工程实践

    • 测试与调试
    • 代码质量
    • 虚拟环境

比较运算符

比较运算符用于判断两个对象之间的关系,返回布尔值 True 或 False。Python 提供了 ==、!=、<、>、<=、>= 六个基本比较运算符,以及独特的链式比较语法,让条件表达更接近数学书写习惯。

基本比较

== 判断两个对象的值是否相等,!= 判断是否不相等。<、>、<=、>= 则用于大小比较。这些运算符的写法与数学符号一致,但 == 使用双等号以区别于赋值运算符 =。

>>> 2 == 2
True
>>> 2 == 3
False
>>> 2 != 3
True
>>> 3 < 5
True
>>> 5 >= 5
True

比较运算符最常见的错误是误用赋值号:

>>> if x = 5:
  File "<stdin>", line 1
    if x = 5:
         ^
SyntaxError: invalid syntax        # 赋值不能出现在条件中

Python 3.8+ 中,如果确实需要在表达式内赋值并比较,应使用海象运算符 :=。

链式比较

Python 支持数学风格的链式比较,这是许多其他语言不具备的特性。表达式 a < b < c 在 Python 中等价于 a < b and b < c,但只计算一次 b。

>>> x = 5
>>> 3 < x < 10
True

>>> 3 < x and x < 10
True        # 等价写法,但 x 被求值两次

链式比较不仅限于同向运算符,可以混合使用:

>>> x = 5
>>> 3 < x <= 5
True        # 3 < 5 and 5 <= 5
>>> 5 <= x < 3
False       # 5 <= 5 and 5 < 3 → True and False
>>> 1 < x < 10 < 100
True        # 可以链任意长度

链式比较中的每个子表达式都会被求值,短路规则依然适用:

>>> def get_value():
...     print("被调用了")
...     return 5
...
>>> 3 < get_value() < 10
被调用了
True
>>> 10 < get_value() < 3
被调用了
False       # 10 < 5 为 False,不再检查 5 < 3

对象比较与 eq

== 比较的是对象的值相等性,而非身份。对于自定义类,Python 默认通过 __eq__ 方法实现比较,如果没有定义,默认行为是比较对象身份(即效果等同于 is)。

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __eq__(self, other):
        if not isinstance(other, Point):
            return NotImplemented
        return self.x == other.x and self.y == other.y

>>> p1 = Point(1, 2)
>>> p2 = Point(1, 2)
>>> p1 == p2
True        # 值相等
>>> p1 is p2
False       # 不是同一个对象

!= 的行为与 == 相反,但如果类定义了 __eq__ 而没有定义 __ne__,Python 会自动从 __eq__ 推导 != 的结果。

>>> p1 != p2
False       # 自动推导为 not (p1 == p2)

对于不可比较的类型,比较运算会返回 NotImplemented 或触发 TypeError:

>>> 3 < "5"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'str'

Python 3 不再支持不同类型之间的隐式大小比较,这避免了 Python 2 中 3 < "5" 这类令人困惑的行为。

浮点数比较陷阱

浮点数在计算机中以二进制近似存储,导致许多直观上相等的值实际上存在微小差异。这是比较运算中最隐蔽的陷阱。

>>> 0.1 + 0.2 == 0.3
False
>>> 0.1 + 0.2
0.30000000000000004

直接比较浮点数是否相等通常是不可靠的。正确的做法是检查差值是否小于某个容差:

>>> abs(0.1 + 0.2 - 0.3) < 1e-9
True

Python 3.5+ 提供了 math.isclose() 函数,专门用于安全的浮点数比较:

>>> import math
>>> math.isclose(0.1 + 0.2, 0.3)
True
>>> math.isclose(1.0, 1.0000001, rel_tol=1e-6)
True
>>> math.isclose(1.0, 1.0000001, rel_tol=1e-9)
False

math.isclose() 使用相对容差和绝对容差组合判断,比手动写 abs(a - b) < epsilon 更健壮。

特殊浮点值 nan(Not a Number)有独特的比较行为:nan 与任何值(包括自身)比较都返回 False。

>>> import math
>>> nan = float('nan')
>>> nan == nan
False
>>> nan != nan
True        # 判断 nan 的唯一可靠方式
>>> math.isnan(nan)
True        # 正确做法

序列和容器的比较

Python 支持序列(列表、元组、字符串等)和容器(字典、集合等)的比较。序列比较是逐元素进行的:

>>> [1, 2, 3] < [1, 2, 4]
True        # 前两个元素相同,第三个 3 < 4
>>> [1, 2] < [1, 2, 3]
True        # 短序列小于长序列(前缀相同的情况下)
>>> "abc" < "abd"
True        # 字符串按字典序比较

字典比较在 Python 3 中仅支持 == 和 !=,不再支持 <、> 等大小比较:

>>> {'a': 1} == {'a': 1}
True
>>> {'a': 1} < {'b': 2}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'dict' and 'dict'

比较运算符的返回值

比较运算符总是返回 True 或 False,但 Python 允许布尔值参与算术运算(True 等价于 1,False 等价于 0)。这种特性偶尔被用于技巧性代码,但不推荐在正式项目中使用:

>>> True + True
2
>>> 5 * (3 > 2)
5

比较运算符是条件判断的基石。链式比较让范围检查变得优雅,而浮点数比较的陷阱提醒我们:计算机中的"相等"与数学中的"相等"并非同一概念。对于精确数值比较,应优先考虑 decimal 模块或 math.isclose()。

上一页
算术运算符
下一页
赋值运算符