一、操作数基础:什么是操作数?为什么需要自定义操作数?操作数在Python中的本质

各位好,咱们开始这门课的第一章。说实话,我教了这么多年Python,发现很多人在「操作数」这个概念上栽过跟头。有人觉得它太简单,扫一眼就过了;有人又觉得它太抽象,搞不懂到底是个啥。

其实没那么复杂。你想想看,我们写代码就是在跟数据打交道。而操作数,就是这些数据在运算时的「身份」。今天我就带你把它的底裤扒干净。

1.1 什么是操作数?

先看一个最朴素的例子:

3 + 5

这里的 3 和 5 就是操作数,+ 是运算符。操作数就是运算符作用的对象。说白了,就是「被操作的东西」。

再复杂一点:

result = (a * b) + (c / d)

这里的 a、b、c、d 都是操作数。它们可以是变量、字面量、函数返回值,甚至是另一个表达式的结果。

核心定义:操作数是表达式中参与运算的基本单元。在Python中,一切能被运算符作用的「东西」都是操作数。

1.2 操作数的常见类型

我习惯把操作数分成三类,这样好记:

类别 示例 说明
字面量 42, 3.14, "hello" 直接写在代码里的值
变量 x, count, user_name 指向内存中某个对象的名称
表达式 (a + b), func() 运算结果作为另一个运算的操作数

举个例子你就明白了:

# 字面量作为操作数
print(10 + 20)      # 10 和 20 都是字面量

# 变量作为操作数
x = 10
y = 20
print(x + y)        # x 和 y 是变量

# 表达式作为操作数
print((x + y) * 2)  # (x + y) 这个表达式的结果是操作数

1.3 为什么需要自定义操作数?

好,问题来了——Python 自带的那些操作数类型(int、float、str、list……)明明够用,为什么还要自己定义?

我在项目中遇到过这样一个场景:需要处理「带单位的数值」,比如 5米 + 3米。用普通 int 行吗?行,但你得自己记住单位。万一有人传了 5米 + 3千克,程序不会报错,结果却毫无意义。

这就是痛点。内置操作数类型无法表达业务语义。你想想看,如果能让 5米 + 3米 自动返回 8米,而 5米 + 3千克 直接抛出异常,是不是爽多了?

我的经验:什么时候该考虑自定义操作数?当你发现代码里到处都在写「转换函数」「校验逻辑」「单位换算」的时候,就是时候了。把这些逻辑封装到操作数里,代码会干净得多。

1.4 操作数在Python中的本质

这里我要说一个很多教程不会讲透的点。在Python里,一切皆对象。操作数也不例外。

你看这个:

a = 10
b = 20
c = a + b

a 和 b 是操作数,它们本质上是 int 类的实例。+ 运算符本质上调用的是 int.__add__ 方法。所以,操作数的本质就是——实现了特定协议的类的实例。

Python 用了一套「魔术方法」(也叫双下方法)来定义操作数的行为:

运算符 对应的魔术方法 说明
+ __add__ 加法
- __sub__ 减法
* __mul__ 乘法
/ __truediv__ 除法
== __eq__ 相等判断
< __lt__ 小于比较

所以,自定义操作数说白了就是——自己写一个类,然后实现这些魔术方法。

注意:我曾经见过有人一口气实现了十几个魔术方法,结果代码又臭又长。我的建议是:只实现你真正需要的。比如你的类只需要加法,那就只写 __add__,别贪多。

1.5 一张图看懂本章知识体系

下面这张图把操作数的概念、分类、本质和自定义动机串起来了。我建议你多看两眼,后面几章都会围绕这个框架展开。

操作数知识体系 操作数 什么是操作数 为什么自定义 本质是什么 字面量 变量 表达式 业务语义 类型安全 代码复用 类的实例 魔术方法 运算符重载 核心结论 自定义操作数 = 定义类 + 实现魔术方法 + 赋予业务语义

1.6 一个简单的自定义操作数示例

光说不练假把式。咱们写一个最简单的自定义操作数——Meter 类,让两个米数能直接相加:

class Meter:
    def __init__(self, value):
        self.value = value
    
    def __add__(self, other):
        if not isinstance(other, Meter):
            raise TypeError(f"不能将 Meter 与 {type(other).__name__} 相加")
        return Meter(self.value + other.value)
    
    def __repr__(self):
        return f"{self.value}米"

# 使用
a = Meter(5)
b = Meter(3)
c = a + b
print(c)  # 输出:8米

# 错误用法
try:
    d = a + 10  # 抛出 TypeError
except TypeError as e:
    print(e)  # 输出:不能将 Meter 与 int 相加

看到了吗?只用了 __add__ 一个魔术方法,就实现了「带单位的加法」。而且类型安全——乱加会报错,不会静默产生垃圾数据。

一个小技巧:我习惯在自定义操作数里加上 __repr__ 方法,这样调试的时候直接打印对象就能看到有意义的信息,不用每次都 .value。省心。

1.7 本章小结

咱们捋一下今天的内容:

  • 操作数就是运算符作用的对象,可以是字面量、变量或表达式
  • 自定义操作数是为了让代码能表达业务语义,同时保证类型安全
  • 本质是类的实例,通过实现魔术方法来定义运算行为