Python 基础:常用运算符介绍 (带演示) – wiki基地


Python 基础:常用运算符介绍 (带演示)

引言

在编程的世界里,运算符是执行各种操作的基石,它们就像语言中的动词,告诉计算机要对数据做什么。无论是进行简单的数学计算、比较数值的大小、判断条件的真假,还是更复杂的数据处理,都离不开运算符的身影。

Python 语言提供了丰富多样的运算符,它们作用于变量和值,执行特定的运算并返回结果。对于初学者来说,熟练掌握这些基本运算符是迈向Python编程的关键一步。

本文将详细介绍 Python 中最常用的一些运算符,包括它们的分类、作用、使用方法,并提供丰富的代码示例进行演示,帮助你深入理解这些重要的概念。

1. 算术运算符 (Arithmetic Operators)

算术运算符用于执行常见的数学运算,如加、减、乘、除等。它们是编程中最基础也是最常用的一类运算符。

运算符 名称 描述 示例 结果
+ 加法 将两个操作数相加 a + b ab 的和
- 减法 第一个操作数减去第二个操作数 a - b ab 的差
* 乘法 两个操作数相乘 a * b ab 的积
/ 除法 第一个操作数除以第二个操作数 a / b ab 的商
// 整除 第一个操作数除以第二个操作数,返回商的整数部分(向下取整) a // b 商的整数部分
% 取模 返回除法的余数 a % b 除法的余数
** 幂运算 第一个操作数的第二个操作数次幂 a ** b ab 次幂

接下来,我们通过代码示例来演示这些算术运算符的使用:

“`python

定义两个变量

a = 10
b = 3

print(f”a = {a}”)
print(f”b = {b}”)
print(“-” * 20) # 分隔线

加法 (+)

sum_result = a + b
print(f”{a} + {b} = {sum_result}”) # 输出: 10 + 3 = 13

减法 (-)

difference_result = a – b
print(f”{a} – {b} = {difference_result}”) # 输出: 10 – 3 = 7

乘法 (*)

product_result = a * b
print(f”{a} * {b} = {product_result}”) # 输出: 10 * 3 = 30

除法 (/)

注意:在 Python 3 中,除法结果总是浮点数

division_result = a / b
print(f”{a} / {b} = {division_result}”) # 输出: 10 / 3 = 3.333…

整除 (//)

向下取整,结果是整数

floor_division_result = a // b
print(f”{a} // {b} = {floor_division_result}”) # 输出: 10 // 3 = 3

整除与负数

x = -10
y = 3
print(f”{x} // {y} = {x // y}”) # 输出: -10 // 3 = -4 (注意:向负无穷方向取整)
print(f”{a} // -{b} = {a // -b}”) # 输出: 10 // -3 = -4 (注意:向负无穷方向取整)

取模 (%)

返回除法的余数

modulo_result = a % b
print(f”{a} % {b} = {modulo_result}”) # 输出: 10 % 3 = 1

取模与负数

余数的符号与除数(右边的操作数)相同

print(f”{x} % {y} = {x % y}”) # 输出: -10 % 3 = 2 (-10 = -4 * 3 + 2)
print(f”{a} % -{b} = {a % -b}”) # 输出: 10 % -3 = -2 (10 = -4 * -3 + -2)

幂运算 (**)

power_result = a ** b # 10 的 3 次幂
print(f”{a} ** {b} = {power_result}”) # 输出: 10 ** 3 = 1000

浮点数的幂运算 (开方)

sqrt_result = 9 ** 0.5 # 9 的 0.5 次幂,即平方根
print(f”9 ** 0.5 = {sqrt_result}”) # 输出: 9 ** 0.5 = 3.0

结合不同类型进行算术运算

整数和浮点数运算的结果通常是浮点数

int_var = 5
float_var = 2.5
mixed_sum = int_var + float_var
print(f”{int_var} + {float_var} = {mixed_sum}”) # 输出: 5 + 2.5 = 7.5

字符串和整数的乘法 (重复字符串)

string_var = “Hello”
repeat_result = string_var * 3
print(f'”{string_var}” * 3 = “{repeat_result}”‘) # 输出: “Hello” * 3 = “HelloHelloHello”

字符串的加法 (拼接字符串)

string1 = “Hello”
string2 = ” World”
concatenation_result = string1 + string2
print(f'”{string1}” + “{string2}” = “{concatenation_result}”‘) # 输出: “Hello” + ” World” = “Hello World”

注意:不能对不同类型进行不兼容的算术运算,例如数字和字符串相加会引发 TypeError

print(10 + “Hello”) # 这行代码会报错!

“`

总结: 算术运算符是进行数值计算的基础。需要特别注意 / 除法的结果是浮点数,// 整除是向下取整,以及 % 取模在涉及负数时的行为。同时,一些算术运算符 (+, *) 也可以用于特定非数值类型(如字符串和列表)来执行拼接或重复操作。

2. 比较运算符 (Comparison Operators / Relational Operators)

比较运算符用于比较两个值,它们总是返回一个布尔值 (TrueFalse),表示比较的结果是否为真。

运算符 名称 描述 示例 结果
== 相等 如果两个操作数相等,则为 True a == b TrueFalse
!= 不相等 如果两个操作数不相等,则为 True a != b TrueFalse
> 大于 如果左边的操作数大于右边的操作数,则为 True a > b TrueFalse
< 小于 如果左边的操作数小于右边的操作数,则为 True a < b TrueFalse
>= 大于或等于 如果左边的操作数大于或等于右边的操作数,则为 True a >= b TrueFalse
<= 小于或等于 如果左边的操作数小于或等于右边的操作数,则为 True a <= b TrueFalse

比较运算符常用于条件判断语句(如 if 语句)和循环语句中。

“`python

定义变量进行比较

a = 10
b = 20
c = 10
d = “Hello”
e = “hello”

print(f”a = {a}, b = {b}, c = {c}, d = ‘{d}’, e = ‘{e}'”)
print(“-” * 20)

相等 (==)

print(f”{a} == {b} ? {a == b}”) # 输出: 10 == 20 ? False
print(f”{a} == {c} ? {a == c}”) # 输出: 10 == 10 ? True
print(f”{d} == {e} ? {d == e}”) # 输出: Hello == hello ? False (字符串比较区分大小写)

不相等 (!=)

print(f”{a} != {b} ? {a != b}”) # 输出: 10 != 20 ? True
print(f”{a} != {c} ? {a != c}”) # 输出: 10 != 10 ? False
print(f”{d} != {e} ? {d != e}”) # 输出: Hello != hello ? True

大于 (>)

print(f”{a} > {b} ? {a > b}”) # 输出: 10 > 20 ? False
print(f”{b} > {a} ? {b > a}”) # 输出: 20 > 10 ? True

小于 (<)

print(f”{a} < {b} ? {a < b}”) # 输出: 10 < 20 ? True
print(f”{b} < {a} ? {b < a}”) # 输出: 20 < 10 ? False

大于或等于 (>=)

print(f”{a} >= {c} ? {a >= c}”) # 输出: 10 >= 10 ? True
print(f”{a} >= {b} ? {a >= b}”) # 输出: 10 >= 20 ? False

小于或等于 (<=)

print(f”{a} <= {c} ? {a <= c}”) # 输出: 10 <= 10 ? True
print(f”{a} <= {b} ? {a <= b}”) # 输出: 10 <= 20 ? True

比较不同类型 (通常会失败或有意外结果)

print(a > d) # 这行代码会报错,数字和字符串不能直接比较大小

比较列表或元组 (按元素顺序比较)

list1 = [1, 2, 3]
list2 = [1, 2, 4]
list3 = [1, 2, 3]
print(f”{list1} == {list3} ? {list1 == list3}”) # 输出: [1, 2, 3] == [1, 2, 3] ? True (值相等)
print(f”{list1} < {list2} ? {list1 < list2}”) # 输出: [1, 2, 3] < [1, 2, 4] ? True (比较到第三个元素 3 < 4)

链式比较

Python 允许链式比较,例如 a < b < c 等价于 (a < b) and (b < c)

x = 15
print(f”{a} < {x} < {b} ? {a < x < b}”) # 输出: 10 < 15 < 20 ? True (因为 10 < 15 为 True 且 15 < 20 为 True)
print(f”{a} < {b} < {c} ? {a < b < c}”) # 输出: 10 < 20 < 10 ? False (因为 20 < 10 为 False)
“`

总结: 比较运算符用于判断值之间的关系。== 用于判断值是否相等,is 用于判断是否是同一个对象(后续会介绍)。理解链式比较是 Python 的一个方便特性。注意不同类型之间通常不能直接进行大小比较。

3. 赋值运算符 (Assignment Operators)

赋值运算符用于将值赋给变量。最基本的赋值运算符是 =。此外,Python 还提供了一系列复合赋值运算符,可以将算术或其他运算与赋值结合起来,使代码更简洁。

运算符 示例 等价于 描述
= a = 1 简单的赋值
+= a += b a = a + b 加法赋值
-= a -= b a = a - b 减法赋值
*= a *= b a = a * b 乘法赋值
/= a /= b a = a / b 除法赋值
//= a //= b a = a // b 整除赋值
%= a %= b a = a % b 取模赋值
**= a **= b a = a ** b 幂运算赋值
&= a &= b a = a & b 按位与赋值
|= a |= b a = a | b 按位或赋值
^= a ^= b a = a ^ b 按位异或赋值
>>= a >>= b a = a >> b 按位右移赋值
<<= a <<= b a = a << b 按位左移赋值

复合赋值运算符的使用示例如下:

“`python

简单赋值

x = 10
print(f”初始值 x = {x}”) # 输出: 初始值 x = 10

加法赋值 (+=)

x += 5 # 等价于 x = x + 5
print(f”x += 5 后, x = {x}”) # 输出: x += 5 后, x = 15

减法赋值 (-=)

x -= 3 # 等价于 x = x – 3
print(f”x -= 3 后, x = {x}”) # 输出: x -= 3 后, x = 12

乘法赋值 (*=)

x = 2 # 等价于 x = x * 2
print(f”x
= 2 后, x = {x}”) # 输出: x *= 2 后, x = 24

除法赋值 (/=)

注意:结果会变成浮点数

x /= 4 # 等价于 x = x / 4
print(f”x /= 4 后, x = {x}”) # 输出: x /= 4 后, x = 6.0

整除赋值 (//=)

y = 10
y //= 3 # 等价于 y = y // 3
print(f”y = 10, y //= 3 后, y = {y}”) # 输出: y = 10, y //= 3 后, y = 3

取模赋值 (%=)

z = 10
z %= 3 # 等价于 z = z % 3
print(f”z = 10, z %= 3 后, z = {z}”) # 输出: z = 10, z %= 3 后, z = 1

幂运算赋值 (**=)

p = 2
p = 3 # 等价于 p = p ** 3
print(f”p = 2, p
= 3 后, p = {p}”) # 输出: p = 2, p **= 3 后, p = 8

复合赋值也适用于其他类型,例如字符串拼接

greeting = “Hello”
greeting += ” World”
print(f’greeting += ” World” 后, greeting = “{greeting}”‘) # 输出: greeting += ” World” 后, greeting = “Hello World”

列表的扩展

my_list = [1, 2]
my_list += [3, 4] # 等价于 my_list = my_list + [3, 4]
print(f”my_list = [1, 2], my_list += [3, 4] 后, my_list = {my_list}”) # 输出: my_list = [1, 2], my_list += [3, 4] 后, my_list = [1, 2, 3, 4]

注意:某些操作符不能用于所有类型,例如乘法赋值对列表是重复元素

my_list_2 = [1, 2]
my_list_2 = 2 # 等价于 my_list_2 = my_list_2 * 2
print(f”my_list_2 = [1, 2], my_list_2
= 2 后, my_list_2 = {my_list_2}”) # 输出: my_list_2 = [1, 2], my_list_2 *= 2 后, my_list_2 = [1, 2, 1, 2]

按位赋值将在下一节的按位运算符中演示

“`

总结: 赋值运算符用于给变量赋予新的值。复合赋值运算符提供了一种简洁的方式来执行操作并更新变量的值,是日常编程中非常常用的语法糖。

4. 逻辑运算符 (Logical Operators)

逻辑运算符用于组合或修改布尔表达式。它们通常用于 if 语句、while 循环以及其他需要进行条件判断的场景。Python 的逻辑运算符是英文单词:and, or, not

运算符 名称 描述 示例 结果
and 逻辑与 如果两个操作数都为 True,则结果为 True x and y 如果 xy 都为 True,则为 True
or 逻辑或 如果两个操作数中至少一个为 True,则结果为 True x or y 如果 xy 中至少一个为 True,则为 True
not 逻辑非 反转操作数的布尔值 not x 如果 x 为 True,则为 False;反之亦然

逻辑运算符具有”短路(Short-circuit)”特性:

  • 对于 and 运算符,如果第一个操作数为 False,则不再评估第二个操作数,直接返回 False
  • 对于 or 运算符,如果第一个操作数为 True,则不再评估第二个操作数,直接返回 True

此外,Python 中的任何对象都可以被视为布尔值:
* FalseNone、数字 0 (包括整数、浮点数、复数)、空序列 (空字符串 "", 空列表 [], 空元组 (), 空字典 {}), 空集合 set() 都被视为 False
* 其他所有值都被视为 True

“`python

定义布尔变量

is_sunny = True
is_warm = False

print(f”is_sunny = {is_sunny}, is_warm = {is_warm}”)
print(“-” * 20)

逻辑与 (and)

只有两个条件都为 True 时,结果才为 True

print(f”is_sunny and is_warm ? {is_sunny and is_warm}”) # 输出: is_sunny and is_warm ? False
print(f”True and True ? {True and True}”) # 输出: True and True ? True
print(f”False and True ? {False and True}”) # 输出: False and True ? False

逻辑或 (or)

只要有一个条件为 True 时,结果就为 True

print(f”is_sunny or is_warm ? {is_sunny or is_warm}”) # 输出: is_sunny or is_warm ? True
print(f”False or False ? {False or False}”) # 输出: False or False ? False
print(f”True or False ? {True or False}”) # 输出: True or False ? True

逻辑非 (not)

反转布尔值

print(f”not is_sunny ? {not is_sunny}”) # 输出: not is_sunny ? False
print(f”not is_warm ? {not is_warm}”) # 输出: not is_warm ? True

逻辑运算符与非布尔值的结合 (利用对象的布尔值)

字符串 “Hello” 被视为 True,空字符串 “” 被视为 False

str1 = “Hello”
str2 = “”
print(f'”{str1}” and “{str2}” ? {“Hello” and “”}’) # 输出: “Hello” and “” ? (短路,返回 “”,其布尔值为 False)
print(f'”{str1}” or “{str2}” ? {“Hello” or “”}’) # 输出: “Hello” or “” ? Hello (短路,返回 “Hello”,其布尔值为 True)
print(f'”{str2}” or “{str1}” ? {“” or “Hello”}’) # 输出: “” or “Hello” ? Hello

数字 10 被视为 True, 数字 0 被视为 False

num1 = 10
num2 = 0
print(f”{num1} and {num2} ? {10 and 0}”) # 输出: 10 and 0 ? 0 (返回 0,其布尔值为 False)
print(f”{num1} or {num2} ? {10 or 0}”) # 输出: 10 or 0 ? 10 (返回 10,其布尔值为 True)

短路特性演示

下面的代码不会引发除零错误,因为 False and 0 / 0 的第一个操作数是 False,and 运算符发生短路

print(f”False and (1 / 0) ? {False and (1 / 0)}”) # 输出: False and (1 / 0) ? False (不会报错)

下面的代码也不会引发除零错误,因为 True or 0 / 0 的第一个操作数是 True,or 运算符发生短路

print(f”True or (1 / 0) ? {True or (1 / 0)}”) # 输出: True or (1 / 0) ? True (不会报错)

如果第一个操作数不足以决定结果,则会评估第二个操作数

print(f”True and (1 / 0) ? {True and (1 / 0)}”) # 这行代码会报错,因为 True and 需要评估第二个操作数

“`

总结: 逻辑运算符用于组合和反转布尔值或具有布尔意义的对象。理解 and, or, not 的行为以及短路特性对于编写条件逻辑至关重要。记住 Python 中哪些值被视为 False 也非常有用。

5. 位运算符 (Bitwise Operators)

位运算符直接操作整数的二进制位。对于初学者来说,这部分内容可能不如前几类常用,但在处理底层数据、进行高效计算或某些特定算法时非常有用。要理解位运算符,你需要先了解整数如何以二进制形式表示。

我们以 10 (二进制 1010) 和 4 (二进制 0100) 为例进行演示。

运算符 名称 描述 示例 结果(十进制) 二进制演示
& 按位与 对应位都为 1 时,结果位才为 1 x & y 10 & 4 = 0 1010 & 0100 = 0000
| 按位或 对应位有一个为 1 时,结果位就为 1 x | y 10 | 4 = 14 1010 | 0100 = 1110
^ 按位异或 对应位不同时,结果位才为 1 x ^ y 10 ^ 4 = 14 1010 ^ 0100 = 1110
~ 按位取反 对每一个二进制位取反 (0 变 1,1 变 0) ~x ~10 = -11 复杂,涉及补码
<< 左移 将二进制位向左移动指定的位数,右侧补 0,相当于乘以 2 的幂 x << n 10 << 1 = 20 1010 << 1 = 10100
>> 右移 将二进制位向右移动指定的位数,左侧补符号位(正数补 0),相当于整除以 2 的幂 x >> n 10 >> 1 = 5 1010 >> 1 = 0101

注意: 按位取反 ~x 的结果在 Python 中是 -(x+1),这涉及到二进制补码表示法,对于初学者可能较难理解。在大多数情况下,记住 ~x 的结果是 -(x+1) 即可。

“`python

定义整数变量

a = 10 # 二进制: 1010
b = 4 # 二进制: 0100
c = 5 # 二进制: 0101

print(f”a = {a} (binary: {a:0>4b})”) # {a:0>4b} 格式化输出为4位二进制,左侧补0
print(f”b = {b} (binary: {b:0>4b})”)
print(f”c = {c} (binary: {c:0>4b})”)
print(“-” * 20)

按位与 (&)

1010 & 0100 = 0000 (0)

bitwise_and_result = a & b
print(f”{a} & {b} = {bitwise_and_result} (binary: {bitwise_and_result:0>4b})”) # 输出: 10 & 4 = 0 (binary: 0000)

1010 & 0101 = 0000 (0) 错了,应该是 0000 (0) 与 0101 (5) -> 0000

1010 & 0101 = 0000 (0) 这个例子是错的。应该是 1010 & 0101 -> 0000

1010 (10) & 0101 (5) = 0000 (0)

bitwise_and_result_2 = a & c
print(f”{a} & {c} = {bitwise_and_result_2} (binary: {bitwise_and_result_2:0>4b})”) # 输出: 10 & 5 = 0 (binary: 0000)

按位或 (|)

1010 | 0100 = 1110 (14)

bitwise_or_result = a | b
print(f”{a} | {b} = {bitwise_or_result} (binary: {bitwise_or_result:0>4b})”) # 输出: 10 | 4 = 14 (binary: 1110)

1010 | 0101 = 1111 (15)

bitwise_or_result_2 = a | c
print(f”{a} | {c} = {bitwise_or_result_2} (binary: {bitwise_or_result_2:0>4b})”) # 输出: 10 | 5 = 15 (binary: 1111)

按位异或 (^)

1010 ^ 0100 = 1110 (14)

bitwise_xor_result = a ^ b
print(f”{a} ^ {b} = {bitwise_xor_result} (binary: {bitwise_xor_result:0>4b})”) # 输出: 10 ^ 4 = 14 (binary: 1110)

1010 ^ 0101 = 1111 (15)

bitwise_xor_result_2 = a ^ c
print(f”{a} ^ {c} = {bitwise_xor_result_2} (binary: {bitwise_xor_result_2:0>4b})”) # 输出: 10 ^ 5 = 15 (binary: 1111)

按位取反 (~)

~10 的结果是 -(10+1) = -11

bitwise_not_result = ~a
print(f”~{a} = {bitwise_not_result}”) # 输出: ~10 = -11

左移 (<<)

10 (1010) 左移 1 位 -> 10100 (20)

left_shift_result = a << 1
print(f”{a} << 1 = {left_shift_result} (binary: {left_shift_result:b})”) # 输出: 10 << 1 = 20 (binary: 10100)

10 (1010) 左移 2 位 -> 101000 (40)

left_shift_result_2 = a << 2
print(f”{a} << 2 = {left_shift_result_2} (binary: {left_shift_result_2:b})”) # 输出: 10 << 2 = 40 (binary: 101000)

右移 (>>)

10 (1010) 右移 1 位 -> 0101 (5)

right_shift_result = a >> 1
print(f”{a} >> 1 = {right_shift_result} (binary: {right_shift_result:b})”) # 输出: 10 >> 1 = 5 (binary: 101)

10 (1010) 右移 2 位 -> 0010 (2)

right_shift_result_2 = a >> 2
print(f”{a} >> 2 = {right_shift_result_2} (binary: {right_shift_result_2:b})”) # 输出: 10 >> 2 = 2 (binary: 10)

位运算符的复合赋值

num = 7 # 二进制 0111
num &= 3 # 等价于 num = num & 3 (0111 & 0011 = 0011)
print(f”7 &= 3 后 num = {num}”) # 输出: 7 &= 3 后 num = 3

num = 7 # 二进制 0111
num |= 10 # 等价于 num = num | 10 (0111 | 1010 = 1111)
print(f”7 |= 10 后 num = {num}”) # 输出: 7 |= 10 后 num = 15
“`

总结: 位运算符直接操作数据的二进制表示。它们在处理标志位、数据编码、或者需要进行位级别操作的场景中非常有用。虽然对于日常应用可能不太常用,但了解它们的工作原理有助于深入理解计算机如何处理数据。

6. 成员运算符 (Membership Operators)

成员运算符用于测试序列(如字符串、列表、元组)或集合中是否包含某个特定的值。

运算符 名称 描述 示例 结果
in 成员 如果在指定的序列中找到值,则为 True x in sequence TrueFalse
not in 非成员 如果在指定的序列中没有找到值,则为 True x not in sequence TrueFalse

“`python

定义序列

my_list = [1, 2, 3, 4, 5]
my_string = “Hello Python”
my_tuple = (10, 20, 30)
my_dict = {‘a’: 1, ‘b’: 2, ‘c’: 3} # 对于字典,in/not in 默认检查键(key)

print(f”my_list = {my_list}”)
print(f’my_string = “{my_string}”‘)
print(f”my_tuple = {my_tuple}”)
print(f”my_dict = {my_dict}”)
print(“-” * 20)

检查元素是否在列表中 (in)

print(f”3 in my_list ? {3 in my_list}”) # 输出: 3 in my_list ? True
print(f”6 in my_list ? {6 in my_list}”) # 输出: 6 in my_list ? False

检查子字符串是否在字符串中 (in)

print(f'”Python” in my_string ? {“Python” in my_string}’) # 输出: “Python” in my_string ? True
print(f'”Java” in my_string ? {“Java” in my_string}’) # 输出: “Java” in my_string ? False
print(f'”hello” in my_string ? {“hello” in my_string}’) # 输出: “hello” in my_string ? False (in 区分大小写)

检查元素是否不在列表中 (not in)

print(f”6 not in my_list ? {6 not in my_list}”) # 输出: 6 not in my_list ? True
print(f”3 not in my_list ? {3 not in my_list}”) # 输出: 3 not in my_list ? False

检查元素是否在元组中 (in)

print(f”20 in my_tuple ? {20 in my_tuple}”) # 输出: 20 in my_tuple ? True
print(f”40 in my_tuple ? {40 in my_tuple}”) # 输出: 40 in my_tuple ? False

检查键是否在字典中 (in)

print(f”‘a’ in my_dict ? {‘a’ in my_dict}”) # 输出: ‘a’ in my_dict ? True (检查键 ‘a’)
print(f”‘z’ in my_dict ? {‘z’ in my_dict}”) # 输出: ‘z’ in my_dict ? False (检查键 ‘z’)

检查值是否在字典中 (需要使用 values() 方法)

print(f”1 in my_dict.values() ? {1 in my_dict.values()}”) # 输出: 1 in my_dict.values() ? True (检查值 1)
print(f”5 in my_dict.values() ? {5 in my_dict.values()}”) # 输出: 5 in my_dict.values() ? False (检查值 5)
“`

总结: 成员运算符 innot in 提供了方便快捷的方式来检查一个元素是否存在于一个集合中,这对于数据查找和条件判断非常实用。

7. 身份运算符 (Identity Operators)

身份运算符用于比较两个变量是否引用了同一个对象(即它们是否指向同一个内存地址),而不是简单地比较它们的值是否相等。

运算符 名称 描述 示例 结果
is 如果两个变量引用同一个对象,则为 True x is y TrueFalse
is not 不是 如果两个变量不引用同一个对象,则为 True x is not y TrueFalse

重要区别:is vs ==

  • is 比较的是两个变量所指向的对象的身份(ID),即内存地址。
  • == 比较的是两个变量所指向的对象的值。

对于不可变类型(如整数、字符串、元组),Python 有时会出于优化目的,让具有相同值的变量指向同一个对象(称为”interning” 或 “缓存”)。但这并不可靠,特别是对于大数字或动态生成的字符串。对于可变类型(如列表、字典、集合),即使它们的值完全相同,通常也会创建新的对象,因此 is 的结果会是 False

“`python

比较数值 (小整数会被缓存)

a = 10
b = 10
c = 20

print(f”a = {a}, b = {b}, c = {c}”)
print(“-” * 20)

值比较

print(f”a == b ? {a == b}”) # 输出: a == b ? True (值相等)
print(f”a == c ? {a == c}”) # 输出: a == c ? False (值不相等)

身份比较 (对于小整数,a 和 b 可能指向同一个对象)

print(f”a is b ? {a is b}”) # 输出: a is b ? True (通常对于 -5 到 256 的整数是 True)
print(f”a is c ? {a is c}”) # 输出: a is c ? False

比较字符串 (短字符串可能被缓存)

str1 = “hello”
str2 = “hello”
str3 = “world”
str4 = “he” + “llo” # 动态拼接的字符串,结果值相同

print(f’str1 = “{str1}”, str2 = “{str2}”, str3 = “{str3}”, str4 = “{str4}”‘)
print(“-” * 20)

值比较

print(f”str1 == str2 ? {str1 == str2}”) # 输出: str1 == str2 ? True
print(f”str1 == str3 ? {str1 == str3}”) # 输出: str1 == str3 ? False
print(f”str1 == str4 ? {str1 == str4}”) # 输出: str1 == str4 ? True

身份比较 (短字符串可能被缓存,动态拼接的不一定)

print(f”str1 is str2 ? {str1 is str2}”) # 输出: str1 is str2 ? True (通常是 True)
print(f”str1 is str3 ? {str1 is str3}”) # 输出: str1 is str3 ? False
print(f”str1 is str4 ? {str1 is str4}”) # 输出: str1 is str4 ? True (Python 优化,会识别并缓存)

比较列表 (可变类型,即使值相同,通常不是同一个对象)

list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = list1 # 让 list3 引用 list1 指向的同一个对象

print(f”list1 = {list1}, list2 = {list2}, list3 = {list3}”)
print(“-” * 20)

值比较

print(f”list1 == list2 ? {list1 == list2}”) # 输出: list1 == list2 ? True (值相等)
print(f”list1 == list3 ? {list1 == list3}”) # 输出: list1 == list3 ? True (值相等)

身份比较

print(f”list1 is list2 ? {list1 is list2}”) # 输出: list1 is list2 ? False (通常是 False,即使值相同)
print(f”list1 is list3 ? {list1 is list3}”) # 输出: list1 is list3 ? True (list3 引用了 list1 的对象)

身份不符 (is not)

print(f”list1 is not list2 ? {list1 is not list2}”) # 输出: list1 is not list2 ? True
print(f”list1 is not list3 ? {list1 is not list3}”) # 输出: list1 is not list3 ? False

检查对象是否为 None (常用场景)

检查变量是否为 None 时,强烈推荐使用 is Noneis not None,而不是 == None!= None

这是因为 None 是一个单例对象(Singleton),保证所有 None 都指向同一个内存地址

my_var = None
if my_var is None:
print(“my_var is None”) # 输出: my_var is None

another_var = 0 # 0 在布尔上下文中是 False
if another_var == None:
print(“another_var == None”) # 不会执行
if another_var is None:
print(“another_var is None”) # 不会执行

注意:某些对象(如用户自定义类的实例)可能重载了 == 运算符,但不会影响 is 的行为。

而 == 可能受到对象的 eq 方法影响。所以用 is None 是最准确和推荐的方式。

“`

总结: 身份运算符 isis not 用于判断两个变量是否指向同一个对象。这与 == 运算符比较对象的值不同。尤其是在判断一个变量是否为 None 时,应使用 is Noneis not None。理解可变和不可变类型在身份比较上的差异也很重要。

8. 运算符优先级 (Operator Precedence)

当一个表达式包含多个不同类型的运算符时,运算符优先级决定了它们的计算顺序。优先级高的运算符会先执行,优先级低的后执行。如果优先级相同,则根据结合性 (Associativity) 从左到右或从右到左计算。

记住完整的优先级表并不容易,也不是必须的。最重要的是理解基本的优先级规则,并在不确定时使用括号 () 来明确指定计算顺序。括号内的表达式总是最先计算。

下面列出了一些常见运算符的优先级(从高到低,同一行的优先级相同):

  • () : 括号 (最高优先级)
  • ** : 幂运算
  • +x, -x, ~x : 一元运算符 (正号, 负号, 按位取反)
  • *, /, //, % : 乘法、除法、整除、取模
  • +, - : 加法、减法
  • <<, >> : 位移运算符
  • & : 按位与
  • ^ : 按位异或
  • | : 按位或
  • comparison, in, not in, is, is not: 比较运算符,成员运算符,身份运算符 (通常优先级较低)
  • not : 逻辑非
  • and : 逻辑与
  • or : 逻辑或 (最低优先级)

示例演示优先级:

“`python

示例 1: 乘法优先级高于加法

print(f”2 + 3 * 4 = {2 + 3 * 4}”) # 结果是 14,因为先计算 3 * 4 = 12,再计算 2 + 12 = 14

使用括号改变优先级

print(f”(2 + 3) * 4 = {(2 + 3) * 4}”) # 结果是 20,因为先计算 (2 + 3) = 5,再计算 5 * 4 = 20

print(“-” * 20)

示例 2: 幂运算优先级高于乘法

print(f”2 * 3 ** 2 = {2 * 3 ** 2}”) # 结果是 18,因为先计算 3 ** 2 = 9,再计算 2 * 9 = 18

示例 3: 逻辑运算符的优先级

not > and > or

print(f”False and True or True = {False and True or True}”)

计算过程:

(False and True) or True

False or True

True

输出: False and True or True = True

print(f”False or True and True = {False or True and True}”)

计算过程:

False or (True and True)

False or True

True

输出: False or True and True = True

示例 4: 比较运算符与逻辑运算符

比较运算符优先级高于逻辑运算符

score = 85
print(f”score > 80 and score < 90 = {score > 80 and score < 90}”)

计算过程:

(score > 80) and (score < 90)

(85 > 80) and (85 < 90)

True and True

True

输出: score > 80 and score < 90 = True

使用链式比较更简洁,其优先级也低于逻辑运算符

print(f”80 < score < 90 = {80 < score < 90}”) # 等价于 (80 < score) and (score < 90)

计算过程:

(80 < score) and (score < 90)

(80 < 85) and (85 < 90)

True and True

True

输出: 80 < score < 90 = True

示例 5: 赋值运算符优先级最低

x = 5
y = 10
z = x + y * 2 # 先计算 y * 2,再计算 x + 结果,最后赋值给 z
print(f”x = {x}, y = {y}, z = x + y * 2 后, z = {z}”) # 输出: x = 5, y = 10, z = x + y * 2 后, z = 25
“`

总结: 了解运算符优先级可以帮助你正确预测表达式的计算结果。不确定时,使用括号是确保代码可读性和正确性的最佳实践。

9. 运算符结合性 (Operator Associativity)

当表达式中出现多个具有相同优先级的运算符时,结合性决定了它们的计算顺序。

  • 左结合 (Left-associative): 大多数运算符是左结合的,例如 +, -, *, /, %, //。这意味着它们从左到右分组计算。
    • 例如:a - b - c 被解析为 (a - b) - c
    • 例如:a / b / c 被解析为 (a / b) / c
  • 右结合 (Right-associative): 幂运算符 ** 是右结合的。
    • 例如:a ** b ** c 被解析为 a ** (b ** c)
  • 非结合 (Non-associative): 比较运算符 ==, !=, >, <, >=, <= 是非结合的(尽管 Python 允许链式比较,这是一种特殊情况,不等同于简单的左右结合)。身份运算符 is, is not 也是非结合的。逻辑运算符 and, or 也不是简单的左右结合,因为它们有短路特性。

示例演示结合性:

“`python

左结合示例

print(f”10 – 5 – 2 = {10 – 5 – 2}”) # 相当于 (10 – 5) – 2 = 5 – 2 = 3

print(f”20 / 4 / 2 = {20 / 4 / 2}”) # 相当于 (20 / 4) / 2 = 5.0 / 2 = 2.5

右结合示例

print(f”2 ** 3 ** 2 = {2 ** 3 ** 2}”) # 相当于 2 ** (3 ** 2) = 2 ** 9 = 512

如果是左结合,结果将是 (2 ** 3) ** 2 = 8 ** 2 = 64,这与实际结果不同

print(f”(2 ** 3) ** 2 = {(2 ** 3) ** 2}”) # 通过括号强制左结合

链式比较的结合性 (特殊情况)

1 < x < 10 是特殊的链式比较,它等价于 (1 < x) and (x < 10)

而不是简单的 1 < (x < 10) 或 (1 < x) < 10

1 < x < 10 是一种语法糖,其行为并非简单的左结合或右结合

“`

总结: 虽然不像优先级那样重要,但了解结合性可以帮助理解在没有括号的情况下,同等优先级的运算符如何被分组计算。幂运算符 ** 的右结合性是一个需要特别记住的例外。链式比较是 Python 独特的语法特性,应理解其等价形式。

结论

运算符是 Python 语言的核心组成部分,它们赋予了程序处理数据和执行逻辑的能力。本文详细介绍了 Python 中常用的算术运算符、比较运算符、赋值运算符、逻辑运算符、位运算符、成员运算符和身份运算符,并通过丰富的代码示例演示了它们的用法和特性。

  • 算术运算符 负责基本的数学计算。
  • 比较运算符 用于判断值之间的关系,结果为布尔值。
  • 赋值运算符 用于给变量赋值,复合赋值运算符简化了常见操作。
  • 逻辑运算符 用于组合和操作布尔表达式,是控制程序流程的关键。
  • 位运算符 操作整数的二进制位,在特定领域有用。
  • 成员运算符 检查元素是否存在于序列或集合中。
  • 身份运算符 判断两个变量是否引用同一个对象。

理解运算符的优先级和结合性可以帮助你正确解析复杂的表达式。

掌握这些基本运算符是编写任何 Python 程序的基础。建议你亲自运行文中的示例代码,尝试修改数值和表达式,观察输出结果,加深理解。在实际编程中,你会频繁地使用这些运算符来构建更复杂的功能。不断练习,你将能够熟练地运用它们,编写出高效、清晰的 Python 代码。

继续学习更高级的 Python 特性,如控制流语句(if, for, while)、函数、数据结构等,你会发现运算符是构建这些高级特性的基石。祝你在 Python 的学习旅程中一切顺利!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部