python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python比较运算符

Python基础指南之比较运算符的使用技巧详解

作者:星河耀银海

如果说编程是让计算机帮我们做决策,那么比较运算就是决策的起点,本文全面介绍了Python中的比较运算符及其使用技巧,希望对大家有所帮助

一、开篇:比较——编程世界的"判断题"

如果说编程是让计算机帮我们做决策,那么比较运算就是决策的起点。每一次if判断、每一次循环控制,背后都离不开比较运算符的身影。它们就像编程世界里的"判断题",返回的不是"对"就是"错"——也就是TrueFalse

先来看一段代码,感受一下比较运算符的日常:

age = 25
if age >= 18:
    print("你已经成年了!")

score = 85
if score == 100:
    print("满分!太棒了!")
elif score >= 60:
    print("及格了,继续加油!")
else:
    print("需要补考哦。")

上面这段代码中,>===这些符号就是比较运算符。它们看似简单,但Python的比较运算符有一些非常优雅的特性——比如链式比较,这是很多其他语言不具备的语法糖,用好了能让你的代码简洁又易读。

今天这篇文章,我们就来全面掌握Python比较运算符的每一个细节,从基础用法到高级技巧,让你写出的判断逻辑既准确又优雅。

二、Python的比较运算符全家福

2.1 六大比较运算符一览

Python共提供了6种比较运算符:

# Python的6种比较运算符

x = 10
y = 20

# 1. 等于 == —— 判断两个值是否相等
print(x == y)    # False
print(x == 10)   # True

# 2. 不等于 != —— 判断两个值是否不相等
print(x != y)    # True
print(x != 10)   # False

# 3. 大于 > —— 判断左边是否大于右边
print(x > y)     # False
print(x > 5)     # True

# 4. 小于 < —— 判断左边是否小于右边
print(x < y)     # True
print(x < 5)     # False

# 5. 大于等于 >= —— 判断左边是否大于或等于右边
print(x >= 10)   # True
print(x >= y)    # False

# 6. 小于等于 <= —— 判断左边是否小于或等于右边
print(x <= 10)   # True
print(x <= y)    # True

2.2 比较运算符的返回值

每一个比较运算的结果都是布尔值——TrueFalse

result = (10 > 5)
print(result)          # True
print(type(result))    # <class 'bool'>

# 比较结果可以直接用于条件判断
if 10 > 5:
    print("10确实大于5")  # 这行会执行

# 也可以赋值给变量,用于后续逻辑
is_adult = age >= 18
is_pass = score >= 60
has_permission = is_adult and is_pass

2.3 比较运算符适用哪些数据类型

比较运算符不仅能比较数字,还能比较很多其他类型:

# 1. 数值类型(int, float, complex的实部比较)
print(10 > 3.5)        # True —— int和float可以混用
print(3.14 < 3.15)     # True

# 2. 字符串 —— 按字典序(Unicode码点)逐字符比较
print("apple" < "banana")    # True —— 'a'的码点小于'b'
print("abc" < "abd")         # True —— 前两个字符相同,'c' < 'd'
print("abc" == "abc")        # True
print("A" < "a")             # True —— 大写字母码点小于小写
print("100" < "20")          # True —— 字符串比较!'1' < '2',不是数值比较!

# 3. 列表、元组 —— 逐元素比较
print([1, 2, 3] == [1, 2, 3])    # True
print([1, 2, 3] < [1, 2, 4])     # True —— 第三个元素3 < 4
print([1, 2] < [1, 2, 3])         # True —— 前面相同,短的更小
print((1, 2) < (1, 3))            # True

# 4. 集合 —— 子集/超集关系
print({1, 2} < {1, 2, 3})    # True —— 真子集
print({1, 2} <= {1, 2})      # True —— 子集(允许相等)

注意:并非所有类型之间都能互相比较。不同类型之间比较可能会引发TypeError

# print(10 < "20")     # TypeError: '<' not supported between instances of 'int' and 'str'
# print([1,2] < 3)     # TypeError
# print({1,2} < [1,2]) # TypeError

三、深入理解 == 与 !=

3.1 == 调用的是eq方法

当你写a == b时,Python底层实际上调用的是a.__eq__(b)

# a == b 等价于 a.__eq__(b)

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __eq__(self, other):
        """自定义相等比较的逻辑"""
        if isinstance(other, Person):
            return self.name == other.name and self.age == other.age
        return False

p1 = Person("张三", 25)
p2 = Person("张三", 25)
p3 = Person("李四", 30)

print(p1 == p2)    # True —— 因为我们的__eq__比较了name和age
print(p1 == p3)    # False

如果不自定义__eq__,默认的==比较的是对象的内存地址(和is一样):

class Simple:
    pass

s1 = Simple()
s2 = Simple()
print(s1 == s2)    # False —— 没有__eq__,比较的是id
print(s1 is s2)    # False

3.2 != 调用的是ne方法

!=对应的是__ne__方法。默认情况下,a != b等价于not (a == b),除非你显式定义了__ne__

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __eq__(self, other):
        if isinstance(other, Person):
            return self.name == other.name and self.age == other.age
        return False
    
    def __ne__(self, other):
        """如果不定义,!= 会自动取 == 的反值"""
        result = self.__eq__(other)
        if result is NotImplemented:
            return result
        return not result

p1 = Person("张三", 25)
p2 = Person("张三", 25)
print(p1 != p2)    # False —— 因为它们相等

3.3 == 与 is 的区别(关键知识点)

这是一个高频面试题,也是初学者最容易踩的坑:

# == 比较的是"值"
# is 比较的是"身份"(是否是同一个对象)

a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(a == b)    # True —— 值相等
print(a is b)    # False —— 但不是同一个对象
print(a is c)    # True —— c就是a,同一个对象

# 生活中的类比:
# == :这两张100元钞票的购买力相同吗?
# is :这是同一张钞票吗?

# 小整数缓存(-5到256)会让is的行为出乎意料
x = 256
y = 256
print(x is y)    # True —— Python缓存了小整数对象

x = 257
y = 257
print(x is y)    # False —— 超出了缓存范围!

# 📝 最佳实践:比较值用 ==,比较None用 is
if name is None:          # ✅ 推荐
    print("名字未设置")

if name == None:          # ⚠️ 不推荐(虽然也能用)
    print("名字未设置")

四、大于、小于与字典序比较

4.1 字符串的字典序比较

字符串比较遵循字典序(lexicographic order),也就是从左到右逐个字符比较其Unicode码点:

# ord()函数查看字符的Unicode码点
print(ord('a'))    # 97
print(ord('b'))    # 98
print(ord('A'))    # 65
print(ord('0'))    # 48

# 逐字符比较过程
# "apple" vs "banana"
# 'a'(97) < 'b'(98) → True,直接返回,不比较后面的字符

print("apple" < "banana")    # True

# 更仔细的逐字符比较
def compare_strings(s1, s2):
    """手动模拟字符串比较过程"""
    for i, (c1, c2) in enumerate(zip(s1, s2)):
        print(f"位置{i}: '{c1}'({ord(c1)}) vs '{c2}'({ord(c2)})")
        if c1 < c2:
            print(f"→ '{c1}' < '{c2}',结果:{s1} < {s2}")
            return
        elif c1 > c2:
            print(f"→ '{c1}' > '{c2}',结果:{s1} > {s2}")
            return
    # 所有字符都相同,比较长度
    if len(s1) < len(s2):
        print(f"→ 前缀相同,{s1}更短,结果:{s1} < {s2}")
    elif len(s1) > len(s2):
        print(f"→ 前缀相同,{s2}更短,结果:{s1} > {s2}")
    else:
        print(f"→ 完全相同,结果:{s1} == {s2}")

compare_strings("abc", "abd")
# 位置2: 'c'(99) vs 'd'(100)
# → 'c' < 'd',结果:abc < abd

print("-" * 40)
compare_strings("abc", "abc")
# → 完全相同,结果:abc == abc

print("-" * 40)
compare_strings("abc", "ab")
# → 前缀相同,ab更短,结果:abc > ab

4.2 常用字符串比较场景

# 1. 版本号比较(简单情况)
def is_newer_version(v1, v2):
    """比较两个版本号,v1是否比v2新"""
    parts1 = [int(x) for x in v1.split('.')]
    parts2 = [int(x) for x in v2.split('.')]
    return parts1 > parts2  # 列表逐元素比较!

print(is_newer_version("3.10.1", "3.9.8"))   # True
print(is_newer_version("2.0.0", "2.0.1"))     # False

# 2. 按字母顺序排序
names = ["张三", "李四", "apple", "Banana", "中文"]
print(sorted(names))
# ['Banana', 'apple', '张三', '李四', '中文']
# 大写字母 < 小写字母 < 中文(按Unicode码点)

# 3. Python风格的字符串排序(忽略大小写)
words = ["apple", "Banana", "Cherry", "date"]
print(sorted(words, key=str.lower))
# ['apple', 'Banana', 'Cherry', 'date']

# 4. 判断字符串是否为有效的数字范围
def is_between(s, low, high):
    """判断字符串s是否在low和high之间(字典序)"""
    return low <= s <= high

print(is_between("cat", "apple", "dog"))     # True
print(is_between("zebra", "apple", "dog"))   # False

4.3 列表和元组的逐元素比较

这是Python非常强大的特性——复合数据结构的逐元素比较:

# 列表比较规则:从索引0开始逐元素比较
# 1. 找到第一个不同的位置,比较该位置的元素
# 2. 如果所有对应位置都相同,则较短的列表"更小"
# 3. 对应位置的元素必须可比较

print([1, 2, 3] > [1, 2, 2])      # True —— 第三个元素3 > 2
print([1, 2] < [1, 2, 0])         # True —— 前缀相同,短的更小
print([1, 2, 3] == [1, 2, 3])     # True
print([] < [0])                    # True —— 空列表小于任何非空列表

# 这个特性在实际开发中非常有用
# 示例1:按多个条件排序
students = [
    ("张三", 85, 18),
    ("李四", 85, 17),
    ("王五", 90, 19),
    ("赵六", 85, 17),
]

# 按成绩降序、年龄升序排序
# 因为我们希望成绩高的排前面,所以用负号
sorted_students = sorted(students, key=lambda s: (-s[1], s[2], s[0]))
for s in sorted_students:
    print(f"{s[0]}: 成绩{s[1]}, 年龄{s[2]}")

# 示例2:判断时间段是否重合
def has_overlap(start1, end1, start2, end2):
    """两个时间段是否有重叠"""
    # 时间段用元组(start, end)表示,可以直接比较
    return start1 < end2 and start2 < end1

print(has_overlap((9, 12), (10, 14)))    # True
print(has_overlap((9, 10), (10, 12)))    # False

五、链式比较:Python的独门绝技

5.1 什么是链式比较

这是Python最优雅的特性之一。在大部分语言中,要判断一个值是否在某个区间内,你需要这样写:

// Java或C语言风格
if (x >= 0 && x <= 100) {
    // x在0到100之间
}

而在Python中,你可以写出几乎和数学表达式一样的代码:

x = 50
if 0 <= x <= 100:
    print("x在0到100之间")  # 数学上写法的直接翻译!

这就是链式比较(chained comparison)。Python允许你将多个比较运算符串联起来,它的含义和你直觉所想完全一致。

5.2 链式比较的底层原理

链式比较的底层实现非常精妙。当你写:

a < b < c

Python实际解析为:

(a < b) and (b < c)

但有一个关键区别:中间表达式只计算一次!

# 假设有一个有副作用的函数
def get_value():
    print("计算值...")
    return 10

# 链式比较
result = 5 < get_value() < 20
# 输出:"计算值..."(只输出一次!)

# 等价于
temp = get_value()
result = (5 < temp) and (temp < 20)
# 而不是:result = (5 < get_value()) and (get_value() < 20)  ← 这会调用两次!

这在实际开发中非常重要,特别是当中间表达式涉及函数调用或属性访问时:

# ✅ 好的写法:链式比较,user.age只计算一次
if 0 <= user.age <= 120:
    print("年龄合法")

# ✅ 等价于手动写法
age = user.age
if 0 <= age and age <= 120:
    print("年龄合法")

# 用and也可以,但要注意user.age会计算两次
if 0 <= user.age and user.age <= 120:
    print("年龄合法")  # 对于简单属性访问,影响不大

5.3 链式比较的各种组合

链式比较可以混合使用不同的比较运算符:

x = 10

# 1. 区间判断
print(0 <= x <= 100)         # True —— x在[0, 100]内
print(0 < x <= 100)          # True —— x在(0, 100]内
print(0 <= x < 10)           # False —— x在[0, 10)内

# 2. 判断是否相等
a = b = 5
print(a == b == 5)           # True —— a等于b且b等于5

c = 10
print(a == b == c)           # False —— a等于b(5==5),但b不等于c(5≠10)

# 3. 递减序列
print(5 > x > 0)             # False —— 5 > 10 为 False
print(100 > x > 5)           # True

# 4. 复杂组合(不常见但合法)
print(1 < 3 > 2)             # True —— 1 < 3 and 3 > 2
print(1 < 3 < 5 > 4 > 2)    # True —— 所有相邻比较都为True

# 5. 包含 != 的链式比较
print(1 != 2 != 3)           # True —— 1 != 2 and 2 != 3
print(1 != 2 != 1)           # True —— 1 != 2 and 2 != 1(注意,2 != 1 True)

5.4 链式比较的常见应用场景

# 场景1:成绩等级判断
score = 85
if 90 <= score <= 100:
    grade = "优秀"
elif 80 <= score < 90:
    grade = "良好"
elif 70 <= score < 80:
    grade = "中等"
elif 60 <= score < 70:
    grade = "及格"
else:
    grade = "不及格"
print(f"成绩{score} → {grade}")

# 场景2:时间范围验证
hour = 14
if 9 <= hour < 18:
    print("工作时间")
elif 18 <= hour < 22:
    print("晚间时段")
else:
    print("休息时间")

# 场景3:坐标范围检测
x, y = 5, 8
if 0 <= x <= 10 and 0 <= y <= 10:
    print(f"点({x}, {y})在矩形区域内")

# 场景4:用户名长度验证
username = "python_master"
if 3 <= len(username) <= 20:
    print("用户名长度合法")
else:
    print("用户名长度应在3到20个字符之间")

# 场景5:温度报警系统
def check_temperature(temp):
    if temp < 0:
        return "❄️ 冰冻警告!"
    elif 0 <= temp < 10:
        return "🥶 寒冷"
    elif 10 <= temp < 25:
        return "😊 舒适"
    elif 25 <= temp < 35:
        return "🌞 温暖"
    elif 35 <= temp < 45:
        return "🔥 高温警告!"
    else:
        return "☠️ 极端温度!"

for t in [-5, 5, 20, 30, 40, 50]:
    print(f"{t}°C: {check_temperature(t)}")

六、浮点数比较的特殊处理

6.1 为什么不能直接用 == 比较浮点数

这是几乎所有编程语言都会遇到的问题:

# 经典案例
print(0.1 + 0.2)           # 0.30000000000000004 —— 不是精确的0.3!
print(0.1 + 0.2 == 0.3)    # False!

# 原因:0.1和0.2在二进制中是无限循环小数
# 就像十进制中 1/3 = 0.3333...
# 计算机只能用有限位二进制近似表示

# 更多令人惊讶的例子
print(0.3 == 0.1 + 0.2)              # False
print(0.5 == 0.25 + 0.25)            # True(0.5可以被精确表示)

6.2 正确的浮点数比较方式

import math

# 方法1:使用math.isclose() —— 推荐!
print(math.isclose(0.1 + 0.2, 0.3))           # True
print(math.isclose(0.1 + 0.2, 0.3, rel_tol=1e-9))  # True

# math.isclose()的参数
# rel_tol: 相对容差(默认1e-9)
# abs_tol: 绝对容差(默认0.0)
print(math.isclose(1e-8, 2e-8, rel_tol=0.5))  # True —— 相对差50%
print(math.isclose(1e-8, 2e-8, abs_tol=1e-7)) # True —— 绝对差1e-8 < 1e-7

# 方法2:自定义容差比较
def approx_equal(a, b, tolerance=1e-9):
    """判断两个浮点数是否近似相等"""
    return abs(a - b) < tolerance

print(approx_equal(0.1 + 0.2, 0.3))           # True
print(approx_equal(0.1 + 0.2, 0.3, 1e-15))    # False —— 容差太小

# 方法3:使用decimal模块进行精确比较
from decimal import Decimal

d1 = Decimal('0.1') + Decimal('0.2')
d2 = Decimal('0.3')
print(d1 == d2)    # True —— 精确的十进制运算!

# 但是Decimal也更慢,适用于金融等对精度有严格要求的场景

# 方法4:对于整数运算的结果,可以直接比较
print(1.0 + 2.0 == 3.0)    # True —— 这些值可以被精确表示

6.3 浮点数比较的最佳实践

import math

# ✅ 推荐做法
def compare_floats(a, b, operation='eq', tolerance=1e-9):
    """安全的浮点数比较"""
    if operation == 'eq':
        return math.isclose(a, b, abs_tol=tolerance)
    elif operation == 'lt':
        return a < b and not math.isclose(a, b, abs_tol=tolerance)
    elif operation == 'le':
        return a < b or math.isclose(a, b, abs_tol=tolerance)
    elif operation == 'gt':
        return a > b and not math.isclose(a, b, abs_tol=tolerance)
    elif operation == 'ge':
        return a > b or math.isclose(a, b, abs_tol=tolerance)
    else:
        raise ValueError(f"Unknown operation: {operation}")

# 测试
x = 0.1 + 0.2
y = 0.3

print(f"x == y: {compare_floats(x, y, 'eq')}")   # True
print(f"x < y:  {compare_floats(x, y, 'lt')}")   # False
print(f"x <= y: {compare_floats(x, y, 'le')}")   # True
print(f"x > y:  {compare_floats(x, y, 'gt')}")   # False
print(f"x >= y: {compare_floats(x, y, 'ge')}")   # True

七、比较运算符与其他运算符的区别

7.1 比较 vs 赋值

这是初学者最容易混淆的两个符号:

# = 是赋值运算符
# == 是比较运算符(等于)

x = 10        # 赋值:把10存入变量x
x == 10       # 比较:x的值是否等于10?返回True

# 常见错误
# if x = 10:     # SyntaxError!=是赋值,不能用在if中
#     print(x)

if x == 10:      # ✅ 正确:比较x是否等于10
    print(x)

# 海象运算符 := (Python 3.8+) —— 在表达式中赋值
# 这个不是比较运算符!
if (n := len("hello")) > 3:
    print(f"字符串长度{n}大于3")

# 一句话总结:
# =  赋值
# == 比较(等于)
# := 表达式内赋值(海象运算符)

7.2 比较 vs 成员 vs 身份

三种运算符各司其职:

# 比较运算符:比较值的大小关系
# ==, !=, >, <, >=, <=

# 成员运算符:判断是否在容器中
# in, not in
print('a' in 'abc')           # True
print(3 in [1, 2, 3, 4])      # True

# 身份运算符:判断是否为同一对象
# is, is not
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b)     # True —— 值相同
print(a is b)     # False —— 不是同一对象

# 三者结合起来使用
def validate_input(value, valid_range, valid_set):
    """综合验证输入"""
    if value is None:
        return False, "值不能为None"
    if not (valid_range[0] <= value <= valid_range[1]):
        return False, f"值不在合法范围{valid_range}内"
    if value not in valid_set:
        return False, f"值不在允许的集合{valid_set}中"
    return True, "验证通过"

print(validate_input(5, (0, 10), {1, 3, 5, 7, 9}))
# (True, '验证通过')

print(validate_input(6, (0, 10), {1, 3, 5, 7, 9}))
# (False, "值不在允许的集合{1, 3, 5, 7, 9}中")

八、实战案例

8.1 密码强度检测器

def check_password_strength(password):
    """检测密码强度,返回评分和建议"""
    score = 0
    suggestions = []
    
    # 检查长度
    if len(password) < 6:
        suggestions.append("密码太短,至少需要6个字符")
    elif 6 <= len(password) < 10:
        score += 1
    elif 10 <= len(password) < 16:
        score += 2
    else:
        score += 3
    
    # 检查是否包含大写字母
    has_upper = any('A' <= c <= 'Z' for c in password)
    if has_upper:
        score += 1
    else:
        suggestions.append("建议添加大写字母")
    
    # 检查是否包含小写字母
    has_lower = any('a' <= c <= 'z' for c in password)
    if has_lower:
        score += 1
    else:
        suggestions.append("建议添加小写字母")
    
    # 检查是否包含数字
    has_digit = any('0' <= c <= '9' for c in password)
    if has_digit:
        score += 1
    else:
        suggestions.append("建议添加数字")
    
    # 检查是否包含特殊字符
    special_chars = set("!@#$%^&*()_+-=[]{}|;:,.<>?")
    has_special = any(c in special_chars for c in password)
    if has_special:
        score += 2
    else:
        suggestions.append("建议添加特殊字符")
    
    # 评分等级
    if score <= 2:
        strength = "弱 🚫"
    elif 3 <= score <= 5:
        strength = "中等 ⚠️ "
    elif 6 <= score <= 7:
        strength = "强 ✅"
    else:
        strength = "非常强 🛡️"
    
    return strength, score, suggestions

# 测试
passwords = ["123456", "abc123", "Abc123!@", "MyP@ssw0rd2024!", "a"]
for pwd in passwords:
    strength, score, suggestions = check_password_strength(pwd)
    print(f"\n密码: {pwd}")
    print(f"强度: {strength} (得分: {score})")
    if suggestions:
        for s in suggestions:
            print(f"  💡 {s}")

8.2 成绩管理系统中的等级评定

def calculate_grade(scores):
    """计算总成绩和等级"""
    if not scores:
        return 0, "无成绩"
    
    total = sum(scores)
    average = total / len(scores)
    
    # 使用链式比较评定等级
    if 90 <= average <= 100:
        grade = "A+"
        comment = "🌟 卓越!继续保持!"
    elif 85 <= average < 90:
        grade = "A"
        comment = "👏 优秀!"
    elif 80 <= average < 85:
        grade = "B+"
        comment = "👍 良好偏上"
    elif 75 <= average < 80:
        grade = "B"
        comment = "🙂 良好"
    elif 70 <= average < 75:
        grade = "C+"
        comment = "📚 中等偏上,还有提升空间"
    elif 60 <= average < 70:
        grade = "C"
        comment = "✏️ 及格,需要更加努力"
    else:
        grade = "F"
        comment = "📖 不及格,请认真复习"
    
    return average, grade, comment

# 批量处理学生成绩
students = {
    "张三": [95, 88, 92, 97, 90],
    "李四": [78, 82, 80, 75, 79],
    "王五": [60, 65, 58, 62, 55],
    "赵六": [45, 52, 48, 50, 55],
}

for name, scores in students.items():
    avg, grade, comment = calculate_grade(scores)
    print(f"{name}: 平均分={avg:.1f}, 等级={grade}, {comment}")

8.3 IP地址范围检测

def ip_to_tuple(ip):
    """将IP地址字符串转换为整数元组"""
    return tuple(int(part) for part in ip.split('.'))

def is_ip_in_range(ip, start_ip, end_ip):
    """判断IP是否在指定范围内(使用链式比较的列表版)"""
    ip_tuple = ip_to_tuple(ip)
    start_tuple = ip_to_tuple(start_ip)
    end_tuple = ip_to_tuple(end_ip)
    
    # 元组的逐元素比较使得IP范围判断非常简单!
    return start_tuple <= ip_tuple <= end_tuple

# 测试
print(is_ip_in_range("192.168.1.50", "192.168.1.1", "192.168.1.100"))   # True
print(is_ip_in_range("192.168.2.1", "192.168.1.1", "192.168.1.254"))    # False
print(is_ip_in_range("10.0.0.5", "10.0.0.0", "10.0.0.255"))             # True

九、常见陷阱与最佳实践

9.1 陷阱1:字符串与数字的"比较"

# ⚠️ Python 3中不能直接比较不同类型
# print("10" > 5)    # TypeError

# 但有些意想不到的情况
print("10" > "5")     # False!因为字符串比较:'1' < '5'
print(10 > 5)         # True  —— 数值比较

# 📝 确保比较时类型一致
def safe_compare(a, b):
    """安全的比较函数——要求类型一致"""
    if type(a) != type(b):
        raise TypeError(f"不能比较{type(a).__name__}和{type(b).__name__}")
    return a > b

# 或者先转换类型
a_str = "10"
b_int = 5
print(int(a_str) > b_int)    # True —— 明确转换后比较

9.2 陷阱2:NaN的比较特性

# NaN(Not a Number)的比较行为非常特殊
import math

nan = float('nan')
print(nan == nan)           # False —— NaN不等于任何值,包括自身!
print(nan != nan)           # True
print(nan > 0)              # False
print(nan < 0)              # False

# 判断NaN的正确方式
print(math.isnan(nan))      # True —— ✅ 推荐方式

# 这在数据处理中非常重要
data = [1.0, 2.0, float('nan'), 3.0, float('nan')]
# 去除NaN值
clean_data = [x for x in data if not math.isnan(x)]
print(clean_data)           # [1.0, 2.0, 3.0]

# 注意:NaN可以导致排序异常
# sorted([1.0, float('nan'), 2.0])  # 在不同Python版本中行为不同

9.3 陷阱3:None的比较

# ✅ 推荐:使用 is 比较 None
x = None
if x is None:           # 推荐
    print("x是None")

if x is not None:       # 推荐
    print("x不是None")

# ⚠️ 不推荐:使用 == 比较 None
if x == None:           # 可以工作,但不推荐
    print("x是None")

# 原因:== 可以被自定义的 __eq__ 覆盖
class Weird:
    def __eq__(self, other):
        return True     # 疯狂的__eq__:和任何值比较都返回True

w = Weird()
print(w == None)         # True —— 但实际上w并不是None!
print(w is None)         # False —— is不会被覆盖,这才是真实情况

# 📝 铁律:比较None永远用 is / is not

9.4 最佳实践总结

# 最佳实践对照表

# 1. 区间判断 → 用链式比较
# ✅
if 0 <= x <= 100:
    pass
# ❌
if x >= 0 and x <= 100:
    pass

# 2. 浮点数比较 → 用math.isclose()
# ✅
import math
if math.isclose(a, b):
    pass
# ❌
if a == b:  # 对于浮点数不安全
    pass

# 3. None判断 → 用is
# ✅
if x is None:
    pass
# ❌
if x == None:
    pass

# 4. 类型判断 → 用isinstance()
# ✅
if isinstance(x, str):
    pass
# ❌
if type(x) == str:
    pass

# 5. 真值判断 → 利用Python的真值规则
# ✅
if my_list:       # 非空列表为True
    pass
# ❌
if len(my_list) > 0:
    pass

# ✅
if name:          # 非空字符串为True
    pass
# ❌
if name != "":
    pass

十、本章小结

本文我们系统性地学习了Python比较运算符的方方面面:

比较运算符虽然简单,但它们是构建条件判断逻辑的基石。掌握这些细节和最佳实践,能让你写出更健壮、更优雅的Python代码。

以上就是Python基础指南之比较运算符的使用技巧详解的详细内容,更多关于Python比较运算符的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文