W
e
l
c
o
m
e
: )

3.Python 中的基础数据类型

Python 中的基础数据类型

本篇导航

本篇讲 Python 的数值型(int / float / 时间)与布尔型,以及围绕它们的
算术、比较、逻辑、同一、位、复合赋值六类运算符和优先级规则。
重点留意:round() 的真实舍入规则、is 与 == 的区别、整数缓存的真相。

本篇输出均为本机实跑

环境 Python 3.13.14。原文若干表述沿用了 Python 2 的说法(如「比较返回 1/0」),
本篇已逐条校正并标注 [!warning] 原文勘误。验证脚本:verify/py03/run03.py(18 组)。


1 为什么要学习数据类型

变量用来存储数据,而生活中的数据类型繁多:例如「我是小红」与 3.14,「我是小红」是一条句子、3.14 是一个数字,二者属于不同类型的数据,支持的操作也不同——句子可以切分成词语,数字可以做加减;存储它们所需的空间大小也不一样。因此,为了方便存储、管理及操作不同类型的数据,Python 对数据的类别做了划分,并让每种类型支持各自的操作。

为应对不同业务需求,Python 把数据分为不同类型,如下图所示:

image-20210306162601034

面试题:

问题:请手写出 Python 中的 7 种数据类型?

答:数值类型、布尔类型、字符串类型、列表类型、元组类型、集合类型、字典类型。

问题:如何判断一个变量到底是什么类型?

答:① 使用 type(变量名称),返回变量的数据类型。

​ ② 使用 isinstance(变量名称, 数据类型),只能返回 True 或 False(真的还是假的)。

注意

Python 变量没有类型,但是 对象有类型。

type() 与 isinstance() 怎么选
  • type(x) is SomeType —— 精确匹配,不考虑继承
  • isinstance(x, SomeType) —— 包含子类,且第二个参数可以是元组(isinstance(x, (int, float)))

日常推荐 isinstance()。典型例子:bool 是 int 的子类,
所以 type(True) is int 为 False,而 isinstance(True, int) 为 True。


2 数值型

2.1 int(整型)

整数:2345, 10, 50。

Python 中,除 10 进制外还有三种进制:

  • 二进制:以 0b 或 0B 开头,数字为 0 1
  • 八进制:以 0o 或 0O 开头,数字为 0 1 2 3 4 5 6 7
  • 十六进制:以 0x 或 0X 开头,数字为 0 1 2 3 4 5 6 7 8 9 a b c d e f

这三种进制可以非常方便地进行位运算,位运算知识后续介绍。

12      # 十进制
0b101   # 二进制
0o10    # 八进制
0xff    # 十六进制
0xf     # 十六进制
0x10    # 十六进制
实跑输出
12    = 12
0b101 = 5
0o10  = 8
0xff  = 255
0xf   = 15
0x10  = 16
原文中 0o19 会让整个文件无法运行

原文代码块里写了 0o19 # 八进制中没有 9。八进制没有数字 9,这会触发语法错误:

SyntaxError: invalid digit '9' in octal literal

注意这是编译期的 SyntaxError,不是运行时异常——意味着含这行的 .py 文件根本无法启动。
本篇已将该行移出代码块改为说明。想看效果可在交互环境单独执行。

image-20220531185230361

Snipaste_2022-05-31_18-53-37

使用 int() 实现类型转换

  1. 浮点数直接舍去小数部分,如 int(9.9) 结果为 9。
  2. 布尔值 True 转为 1,False 转为 0,如 int(True) 结果为 1。
  3. 字符串若符合整数格式(浮点数格式不行),则直接转为对应整数,否则报错。
# 类型转换
int(9.9)      # 浮点数直接舍去小数部分
int(True)     # 布尔类型 True 为 1
int(False)    # 布尔类型 False 为 0
int('456')    # 字符串符合整数格式转换成对应整数
实跑输出
int(9.9)    = 9
int(True)   = 1
int(False)  = 0
int('456')  = 456
下面两种会报 ValueError
int('3.14')     # 字符串是浮点格式
int('3.14ab')   # 字符串含非数字部分
ValueError: invalid literal for int() with base 10: '3.14'
ValueError: invalid literal for int() with base 10: '3.14ab'

想转浮点字符串要先转 float 再转 int:int(float('3.14')) → 3。

Snipaste_2022-05-31_19-02-04
Snipaste_2022-05-31_19-02-19

自动转型

整数和浮点数混合运算时,表达式结果自动转型成浮点数。比如:2+8.0 的结果是 10.0。

# 自动转型
2 + 8.0
实跑输出
10.0

Snipaste_2022-05-31_19-04-35

整数可以有多大

Python 2 中,int 是 32 位,可存储 -2147483648 到 +2147483647 的整数(约 ±21 亿);long 类型是 64 位,可存储 $-2{63}$~$2$ 之间的数值。

Python 3 中,int 可以存储任意大小的整数,long 被取消。甚至可以存储下面这样的值:

googol = 10 ** 100
googol
实跑输出
10 ** 100 的位数: 101
值: 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
类型: int
2 ** 1000 位数: 302   ✅ 不溢出

Snipaste_2022-05-31_19-09-09

Python 3 中可以做超大数的计算而不会造成整数溢出,这也是 Python 特别适合科学运算的原因。

long 去哪了

Python 3 把 int 和 long 合并为 int,自动扩精度,所以不再有 10L 这种写法,
也不会有 OverflowError。代价是超大整数的运算会比机器字长慢。

2.2 float(浮点型)

小数:3.14,或科学计数法 314e-2。

浮点数类型称为 float。

浮点数用 $a*b^{10}$ 形式的科学计数法表示,例如 3.14 可写成 314E-2 或 314e-2。

这些数字在内存中也按科学计数法存储。

# 浮点数
3.14
314e-2   # 科学计数法
314E-2   # 科学计数法
实跑输出
314e-2 = 3.14
314E-2 = 3.14
3.14   = 3.14

Snipaste_2022-05-31_19-19-11

浮点数的经典陷阱(原文未提,必知)
print(0.1 + 0.2)
0.30000000000000004

原因:十进制的 0.1 在二进制中是无限循环小数,只能近似存储(IEEE 754)。

不要直接用 == 比较浮点数:

0.1 + 0.2 == 0.3        # False

正确做法二选一:

import math
math.isclose(0.1 + 0.2, 0.3)          # True,推荐
abs((0.1 + 0.2) - 0.3) < 1e-9         # True,手写容差

涉及金额请用 decimal.Decimal,不要用 float。

类型转换和四舍五入

  1. 与 int() 类似,也可以用 float() 把其他类型转成浮点数。

  2. 整数与浮点数混合运算时,结果自动转型为浮点数,如 2 + 8.0 结果为 10.0。

  3. round(value) 可返回四舍五入的值。

    注:它不会改变原值,而是产生一个新值。

# 类型转换
float(10)     # 整数转浮点数
float(True)   # 布尔转浮点数
float(False)
float('123')  # 字符串转浮点数

# 浮点数转整数
int(3.6)      # 用 int() 转直接舍去小数部分
round(3.6)    # 用 round() 可以实现四舍五入

import math
print(math.ceil(3.6))    # 右取整,上取整 4
print(math.floor(3.6))   # 左取整,下取整 3 与 int 函数功能相同
实跑输出
float(10)    = 10.0
float(True)  = 1.0
float(False) = 0.0
float('123') = 123.0
int(3.6)     = 3
round(3.6)   = 4
math.ceil(3.6)  = 4
math.floor(3.6) = 3
原文勘误:round() 不是四舍五入

原文写「round(value) 可以返回四舍五入的值」。实测打脸:

for v in [0.5, 1.5, 2.5, 3.5, 4.5]:
    print(v, round(v))
0.5 -> 0
1.5 -> 2
2.5 -> 2     ← 不是 3!
3.5 -> 4
4.5 -> 4     ← 不是 5!

Python 3 用的是「银行家舍入」(round half to even,四舍六入五取偶):
当恰好是 .5 时,舍入到最近的偶数,以减少统计上的累计偏差。

官方文档原话:if two multiples are equally close, rounding is done toward the even choice。

想要传统「四舍五入」,自己实现:

import decimal
def round_half_up(x):
    return int(decimal.Decimal(str(x)).quantize(decimal.Decimal('0'), rounding=decimal.ROUND_HALF_UP))

print(round_half_up(2.5), round_half_up(3.5))    # 3 4
3 4

另外 round(2.675, 2) 会得到 2.67 而不是 2.68——同样是浮点存储导致的,金融计算请一律用 Decimal。

原文此处另一处笔误

原文写 float('123d') # 字符串包含非数字部分,报错。注释里的 '123d' 应带引号,
实际是字符串不是裸标识符。报错为:

ValueError: could not convert string to float: '123d'

Snipaste_2022-05-31_19-46-21

Snipaste_2022-05-31_19-46-42

Snipaste_2022-05-31_19-46-50

int() 截断 vs math.floor() 的区别

对正数两者结果相同;对负数不同:

int(-3.6)        = -3     (向 0 截断)
math.floor(-3.6) = -4     (向下取整)

原文说 math.floor 与 int 功能相同,只对正数成立。

2.3 时间的表示

计算机中时间的表示从 1970 年 1 月 1 日 00:00:00 开始,以秒计算。我们也把 1970 年这个时刻称为 Unix 时间点。

这样,时间就全部可以用数字来表示了。

图片8

Python 中可以通过 time.time() 获得当前时刻,返回以秒为单位、带微秒(1/1000 毫秒)精度的浮点值。

例如:

import time
b = time.time()
print(type(b))
print(b)
int(b)
total_minutes = b / 60
total_minutes
total_minutes = b // 60
total_hours = total_minutes // 60
total_days = total_hours // 24
total_years = total_days // 365
实跑输出(运行时值)
type = <class 'float'>
time.time() = 1791703465.9802387
转成日期 = 2026-10-11 15:24:25

Snipaste_2022-05-31_20-42-31

Snipaste_2022-05-31_20-42-43

原文勘误:Unix 时间戳的单位是秒,不是毫秒

原文写「从 1970-01-01 开始,以毫秒(1/1000 秒)进行计算」,这是错的。

实测反证:若真是毫秒,当前值 1791703465 毫秒 = 1791703 秒,
换算成日期是 1970 年(因为 179 万秒 ≈ 20.7 天),明显不合理。

正确:time.time() 返回 Epoch 秒数(float),小数部分提供微秒级精度。

顺带记住三个常用换算:

函数 单位 典型值
time.time() 秒(float,含小数) 1791703465.98
time.time_ns() 纳秒(int) 1791703465980238700
time.time() * 1000 毫秒(需自己乘) 1791703465980.2

原文后半句「带微秒(1/1000 毫秒)精度」是对的(1 微秒 = 1/1000 毫秒)。

2.4 数字和算数运算符

Python 支持整数(如 50、520)和浮点数(如 3.14、10.0、1.23e2),可以对数字做如下运算。

运算符 说明 示例 结果
+ 加法 3+2 5
- 减法 30-5 25
* 乘法 3*6 18
/ 浮点数除法 8/2 4.0
// 整数除法 7//2 3
% 模(取余) 7%4 3
** 幂 2**3 8
a = 7 / 2   # 除法结果为小数
a = 7 // 2  # 整除结果为整数
a = 7 % 2   # 取余
7 % 4
2 ** 3      # 幂运算
divmod(10, 5)  # 返回一个元组,(整除结果, 余数)
divmod(10, 3)
实跑输出
7 / 2  = 3.5
7 // 2 = 3
7 % 2  = 1
2 ** 3 = 8
divmod(10, 5) = (2, 0)
divmod(10, 3) = (3, 1)
原文中 3 / 0 会让程序在此中断

原文代码块里有 3 / 0 # 除数为 0 ,报异常 ZeroDivisionError。
该行会抛异常并终止后续所有语句,因此本篇把它移出代码块单独说明:

ZeroDivisionError: division by zero

想拿到「商 + 余数」推荐用 divmod(),它一次返回二元组,且对负数也符合 Python 语义。

Snipaste_2022-05-31_20-13-08

Snipaste_2022-05-31_20-13-20

使用 divmod() 函数同时得到商和余数:

divmod(13, 3)
实跑输出
(4, 1)

divmod() 是一个函数(后续详细介绍),返回一个元组(后续也会学到)。

// 与 % 对负数的行为(Python 与其他语言不同)
-7 // 2  = -4     (向下取整,不是向 0 截断)
-7 % 2   = 1      (余数符号跟随**除数**,与 C/Java 不同)
7 // -2  = -4

恒等式始终成立:(a // b) * b + (a % b) == a。

2.5 复合赋值运算符

运算符 +、-、*、/、//、**、% 与赋值符 = 结合,可以构成复合赋值运算符。

a = a + 1 等价于 a += 1:

运算符 例子 等价
+= a += 2 a = a + 2
-= a -= 2 a = a - 2
*= a *= 2 a = a * 2
/= a /= 2 a = a / 2
//= a //= 2 a = a // 2
**= a **= 2 a = a ** 2
%= a %= 2 a = a % 2
注意

+= 中间不能加空格。

实跑验证
a=10; a+=2  -> 12
a//=3       -> 4
a**=2       -> 16

3 布尔型

Python 2 中没有布尔值,直接用数字 0 表示 False、数字 1 表示 True。

Python 3 中,True 和 False 被定义为关键字,但它们的本质仍是 1 和 0,甚至可以与数字相加。

bool 类型是 int 类型的一个子类。

注意

在 Python 底层,布尔值 True 被看作 1、False 被看作 0。尽管表面上 True 与 1、False 与 0 是完全不同的两个值,但实际上它们是相同的。

a = True
b = 3
a + b
b = True
isinstance(b, int)
实跑输出
True + 3 = 4
isinstance(True, int) = True
bool.__mro__ = ['bool', 'int', 'object']

Snipaste_2022-05-31_20-53-55

Snipaste_2022-05-31_21-02-36

补充:Python 2 其实也有 bool

原文说「Python2 中没有布尔值」——不准确。
bool 类型自 Python 2.3(PEP 285)就已引入,Python 2 同样有 True/False。
准确说法是:Python 2 中 True/False 是可以被重新赋值的内置名称(不是关键字),
而 Python 3 把它们提升为关键字,不可再赋值:

True = 0     # Python 3: SyntaxError: cannot assign to True

True 代表 1、False 代表 0,但更重要的是:Python 中任何一个数据对象要么为 True、要么为 False,因此可以直接用在布尔测试的表达式中,不必非要通过大小比较或函数测试。

if "a":
    pass
while 1:
    pass

可以用 bool() 函数测试数据对象、表达式是 True 还是 False。例如:

关于原文此处的外链

原文此处附了一个指向 D:\咸鱼仔的知识库\...\bool().md 的绝对路径链接,
该路径属于另一台机器,在本库中必然是断链,故本篇移除。

print(bool())
print(bool(0))
print(bool(1))
print(bool('a'))
print(bool(''))
实跑输出
bool()         -> False
bool(0)        -> False
bool(1)        -> True
bool('a')      -> True
bool('')       -> False

Snipaste_2022-05-31_21-05-32

常见数据类型的真假:

  1. 整数值 0、浮点数值 0.0 等,以及空字符串,都为假。
  2. None 为假。
  3. 空数据对象都为假,如 []、{}、() 等。
实跑:完整的真假表
bool()             -> False
bool(0)            -> False
bool(1)            -> True
bool('a')          -> True
bool('')           -> False
bool(None)         -> False
bool([])           -> False
bool({})           -> False
bool(())           -> False
bool(set())        -> False
bool(range(0))     -> False
bool(0.0)          -> False
注意

Python 中有一些特殊的布尔类型值为 False,例如 False、0、0.0、空值 None、空序列对象(空列表、空元组、空集合、空字典、空字符串)、空 range 对象、空迭代对象。其他情况均为 True。

注意

元组的括号与逗号有其特殊性。例如 (None)、(1) 都不是元组,而是单个数据对象;加上逗号才算元组,如 (None,)、(1,)。所以用括号包围却不是元组的数据,若其本身为假,则整体返回假。

原文勘误:(()) 其实是空元组

原文举例 (())、(None)、(1) 说「这些都不是元组」。实测:

for expr in ["(())", "(None)", "(1)", "()", "((),)", "(None,)", "(1,)"]:
    v = eval(expr)
    print(f"{expr:<10} -> type={type(v).__name__:<8} value={v!r}")
(())       -> type=tuple    value=()
(None)     -> type=NoneType value=None
(1)        -> type=int      value=1
()         -> type=tuple    value=()
((),)      -> type=tuple    value=((),)
(None,)    -> type=tuple    value=(None,)
(1,)       -> type=tuple    value=(1,)

(None) 和 (1) 确实不是元组(因为缺逗号),但 (()) 是空元组——
外层括号只是分组,里层的 () 本身就是空元组。
所以"用括号包围的假值整体为假"这个结论对 (()) 不成立:bool((())) 是 False 没错,
但原因是空元组本身为假,而不是"括号里的东西为假"。

3.1 比较运算符

所有比较运算符返回 True 表示真,返回 False 表示假。

以下假设变量 a 为 15、变量 b 为 30:

运算符 描述 实例
== 等于——比较对象的值是否相等 (a == b) 返回 False
!= 不等于——比较两个对象的值是否不相等 (a != b) 返回 True
> 大于——返回 x 是否大于 y (a > b) 返回 False
< 小于——返回 x 是否小于 y (a < b) 返回 True
>= 大于等于——返回 x 是否大于等于 y (a >= b) 返回 False
<= 小于等于——返回 x 是否小于等于 y (a <= b) 返回 True
a = 15
b = 30

print(f"a == b: {a == b}")
print(f"a != b: {a != b}")
print(f"a > b: {a > b}")
print(f"a < b: {a < b}")
print(f"a >= b: {a >= b}")
print(f"a <= b: {a <= b}")
实跑输出
a == b: False
a != b: True
a > b: False
a < b: True
a >= b: False
a <= b: True

原文勘误:返回的不是 1/0,而是 True/False

原文写「所有比较运算符返回 1 表示真,返回 0 表示假」——这是 Python 2 的老说法。

实测:

15 > 3        -> True
type(15 > 3)  -> bool
(15>3) == 1   -> True    (值相等)
(15>3) is 1   -> False   (不是同一个对象!)

Python 3 返回的是 bool 类型。因为 bool 是 int 的子类,所以 == 1 成立,
但类型不同。写 if (a > b) == 1: 虽然能跑,却是坏味道,应直接写 if a > b:。

3.2 逻辑运算符

运算符 格式 说明
or 逻辑或 x or y x 为 True,则不计算 y,直接返回 True
x 为 False,则返回 y
and 逻辑与 x and y x 为 True,则返回 y 的值
x 为 False,则不计算 y,直接返回 False
not 逻辑非 not x x 为 True,返回 False
x 为 False,返回 True
x = True
y = False

print(f"x and y: {x and y}")
print(f"x or y: {x or y}")
print(f"not x: {not x}")
print(f"not y: {not y}")
实跑输出
x and y: False
x or y: True
not x: False
not y: True

and / or 返回的是操作数,不是布尔值

这是 Python 的特性,也是常用技巧:

print(0 or 'default')     # 'default'
print('' or [])           # []
print(2 and 3)            # 3

返回规则:

  • x or y:x 为真 → 返回 x;否则返回 y
  • x and y:x 为假 → 返回 x;否则返回 y

所以 a = a or default 是设置默认值的惯用写法(但要小心 0、'' 也会被视为假)。
Python 3.8+ 的海象运算符 := 与 f-string 场景下更推荐显式 if ... is None。

3.3 同一运算符

同一运算符用于比较两个对象的存储单元,实际比较的是对象的地址。

运算符 描述
is is 是判断两个标识符是不是引用同一个对象
is not is not 是判断两个标识符是不是引用不同对象

is 与 == 的区别:

  1. is 判断两个变量引用的对象是否为同一个,即比较对象地址。
  2. == 判断两个变量引用对象的值是否相等,默认调用对象的 __eq__() 方法。
a = ['str', 1]
b = ['str', 1]

print('a的地址:', id(a))
print('b的地址:', id(b))
print('a的内容:', a)
print('b的内容:', b)
print('a == b:', a == b)
print('a is b:', a is b)
实跑输出
a的地址: 1992147852672
b的地址: 1992147853376
a的内容: ['str', 1]
b的内容: ['str', 1]
a == b: True      ← 内容相同
a is b: False     ← 不是同一个对象

整数缓存问题

  • 命令行模式下,Python 仅对较小的整数对象进行缓存(范围 [-5, 256]),并非所有整数。
    C 语言底层用数组实现,连续分配空间,便于查找。
  • 文件模式下,所有数字都会被缓存,范围是 [-∞, +∞]。
    • 缓存实现:[-5, 256] 仍用数组实现;不在 [-5, 256] 范围内的数,缓存到链表中,不连续分配空间。

总结

  1. is 比较两个对象的 id 值是否相等,是否指向同一内存地址;
  2. == 比较两个对象的内容是否相等,值是否相等;
  3. is 运算符比 == 效率高,在变量与 None 比较时,应使用 is。
a = ['str', 1]
b = ['str', 1]

print('a的地址:', id(a))
print('b的地址:', id(b))
print('a的内容:', a)
print('b的内容:', b)
print('a == b:', a == b)
print('a is b:', a is b)

# 整数缓存问题
c = 1000
d = 1000

print(f'c的内容{c}; c的地址:{id(c)}')
print(f'd的内容{d}; d的地址:{id(d)}')
print('c == d:', c == d)
print('c is d:', c is d)
实跑输出(本文件以脚本方式运行)
c = 1000; d = 1000
c == d : True
c is d : True
a1 = -6;  b1 = -6   -> a1 is b1 : True
e  = 256; f  = 256  -> e  is f  : True
g  = 257; h  = 257  -> g  is h  : True

原文勘误:「文件模式下所有数字都会缓存,范围 [-∞,+∞]」说法不严谨

实测确实出现 257 is 257 -> True,但原因不是「全局缓存所有整数」,而是:

常量折叠(constant folding)——编译器在同一个编译单元(一个模块/一个交互命令)内,
把重复出现的相同字面量合并成同一个常量对象。

两者的区别很关键:

机制 范围 触发条件
小整数缓存 [-5, 256] CPython 启动时预建,全局生效,跨模块也成立
常量折叠 无范围限制 仅限同一编译单元内的相同字面量

跨单元就不成立了,例如:

# a.py
X = 1000
# b.py
from a import X
Y = 1000
print(X is Y)      # 很可能 False(不同编译单元)

动态创建的就更不可能相等:

x = 1000
y = int("1000")
print(x == y, x is y)     # True  False

实践结论:永远不要用 is 比较数值,只用它比较 None / True / False 这类单例。

注意

上面例子中整数的缓存案例只有在命令行模式下才能复现,在 PyCharm 等 IDE 中无法复现,因为 IDE 对其做了扩充,所有整数都会被缓存。

为什么推荐 x is None 而不是 x == None
  1. None 是单例,is 判断身份最快也最准确
  2. == 可被 __eq__ 重载,自定义对象可能让 x == None 返回奇怪结果
  3. PEP 8 明确推荐:Comparisons to singletons like None should always be done with is or is not

同理适用于 True / False(但要注意 1 == True 成立,而 1 is True 不成立)。


4 基本运算符

前面我们讲解了 +、-、*、/、//、% 等运算符,这里继续讲解其他运算符,并进行学习和测试。

运算符 说明
and,or,not 布尔与、布尔或、布尔非
is,is not 同一性判断,判断是否为同一个对象
<,<=,>,>=,!=,== 比较值是否相当,可以连用
| ^ & 按位或,按位异或、按位与
<<,>> 移位
~ 按位翻转
+,-,*,/,//,% 加,减,乘,浮点除、整数除、取余
** 幂运算
  1. 比较运算符可以连用,含义与日常写法完全一致。
a = 4
3 < a < 10  # 关系运算符可以连用
实跑输出
True

3 < a < 10 等价于 3 < a and a < 10,且 a 只求值一次——这是链式比较的真正优势。

Snipaste_2022-06-03_20-44-05

  1. 位操作
a = 0b11001
b = 0b01000

c = a | b  # 按位或
d = a & b  # 按位与
e = a ^ b  # 按位异或

print(f'c的值:{c}', f'c的二进制表示:{bin(c)}')
print(f'a:{bin(a)}')
print(f'b:{bin(b)}')
print(f'c:{bin(c)}')
print(f'd:{bin(d)}')
print(f'e:{bin(e)}')

a = 4
# 左移 1 位相当于乘以 2; 左移 2 位,相当于乘以 4
print(a << 2)
# 右移 1 位相当于除以 2
print(a >> 1)
实跑输出
a = 0b11001  b = 0b1000
a | b = 0b11001  (25)
a & b = 0b1000   (8)
a ^ b = 0b10001  (17)
4 << 2 = 16   (左移 2 位 = ×4)
4 >> 1 = 2    (右移 1 位 = ÷2)

Snipaste_2022-06-03_21-53-16

  1. 加法操作

    • 数字相加 3+2 ==> 5

      3 + 2
      

      Snipaste_2022-06-03_22-05-52

    • 字符串拼接 "3"+"2" ==> "32"

      '3' + '2'
      

      Snipaste_2022-06-03_22-00-34

    • 列表、元组等合并 [10,20,30]+[5,10,100] ==> [10,20,30,5,10,100]

      [10, 20, 30] + [5, 10, 100]
      

      Snipaste_2022-06-03_22-07-45

  2. 乘法操作

    • 数字相乘 3 * 2 ==> 6

      3 * 2
      

      Snipaste_2022-06-03_22-13-51

    • 字符串复制 "sxt" * 3 ==> "sxtsxtsxt"

      'sxt' * 3
      

      Snipaste_2022-06-03_22-15-21

    • 列表、元组等复制 [10,20,30] * 3 ==> [10,20,30,10,20,30,10,20,30]

      [10, 20, 30] * 3
      

      Snipaste_2022-06-03_22-16-32

实跑输出汇总(+ 与 * 的多态)
3 + 2              = 5
'3' + '2'          = '32'
[10,20,30] + [5,10,100] = [10, 20, 30, 5, 10, 100]
3 * 2              = 6
'sxt' * 3          = 'sxtsxtsxt'
[10,20,30] * 3     = [10, 20, 30, 10, 20, 30, 10, 20, 30]
列表乘法的浅拷贝陷阱(原文未提,高频踩坑)
a = 0 * 3        # 三个元素指向**同一个**子列表
a[0][0] = 1
print(a)             # [[1], [1], [1]]  ← 改一个,全变了

正确做法用列表推导:

a = [[0] for _ in range(3)]
a[0][0] = 1
print(a)             # [[1], [0], [0]]  ✅

5 复合赋值运算符

复合赋值可以让程序更精炼、提高效率。

运算符 描述 示例 等价于
+= 加法赋值 字符串拼接 sum += n
a += "sxt"
sum = sum + n
a = a + "sxt"
-= 减法赋值 num1 -= n num = num - n
*= 乘法赋值 a *= b a = a * b
/= 浮点除赋值 a /= b a = a / b
//= 整数除赋值 a //= b a = a // b
%= 取余赋值 a %= b a = a % b
**= 幂运算赋值 a **= 2 a = a ** 2
<<= 左移赋值 a <<= 2 a = a << 2
>>= 右移赋值 a >>= 2 a = a >> 2
&= 按位与赋值 a &= b a = a & b
|= 按位或赋值 a |= b a = a | b
^= 按位异或赋值 a ^= b a = a ^ b

注:与 C 和 Java 不同,Python 不支持自增(++)和自减(--)

++a 不会报错,是个静默陷阱

原文只说「不支持 ++/--」,但没说 ++a 其实能跑:

a = 5
print(++a)      # 5,等于 +(+a)
print(--a)      # 5,等于 -(-a)
print(a)        # 5,a 本身**没有变**
5
5
5

只有后置的 a++ 才会报 SyntaxError: invalid syntax。

所以从 C/Java 转过来的人写 ++i 不会报错,但循环会变成死循环(i 根本没加)。
Python 里自增只能写 i += 1。


6 运算符优先级问题

如下优先级从高到低排列。

运算符 描述
** 指数(最高优先级)
~ 按位翻转
* / % // 乘,除,取模和取整除
+ - 加法减法
>> << 右移,左移运算符
& 位 'AND'
^ | 位运算符
<= < > >= 比较运算符
== != 等于运算符
is is not 身份运算符
in not in 成员运算符
not or and 逻辑运算符

实际使用中,记住如下简单规则即可,复杂表达式一定要用小括号组织。

  1. 乘除优先加减
  2. 位运算和算术运算 > 比较运算符 > 赋值运算符 > 逻辑运算符
原文勘误(三处,均关于这张优先级表)
  1. 赋值运算符不该出现在优先级表里。Python 中 a = 1 是语句而非表达式,
    没有"优先级"可言。原文表里的 = %= /= //= -= += *= **= 一行应删除。
    (唯一例外是 Python 3.8+ 的海象运算符 :=,它是表达式,且优先级最低。)
  2. <> 是 Python 2 的写法,Python 3 已移除。原文"等于运算符"一行写作 <> == !=,
    其中 <> 在 Python 3 中会直接 SyntaxError,应改为 == !=。
  3. 比较类运算符其实是同一级。原文把 <= < > >= 和 == != 拆成两行,
    又把 is / in 单独排在后面。实际上 Python 官方文档把它们归为同一优先级:
    in / not in / is / is not / < / <= / > / >= / != / ==。
实测:官方优先级(从低到高)
1. lambda
2. if-else(三元表达式)
3. or
4. and
5. not x
6. in / not in / is / is not / < / <= / > / >= / != / ==     ← 同一级
7. |
8. ^
9. &
10. <<  >>
11. +  -
12. *  @  /  //  %
13. +x  -x  ~x(一元)
14. **                                                        ← 最高
两个高频优先级坑(实测)
print(-2 ** 2)          # -4,不是 4!** 优先于一元负号 → -(2**2)
print(not True or True) # True,not 优先于 or → (not True) or True
-4
True

想避免歧义就加括号:(-2) ** 2 = 4。


7 术语表(重要英文单词)

7.1 数据类型

术语 全拼 / 说明 释义
int Integer 整型,Python 3 中任意精度,不会溢出
float Floating-point number 浮点型,IEEE 754 双精度,有精度误差
bool Boolean 布尔型,True / False;是 int 的子类
NoneType — None 的类型,表示"无",单例
literal — 字面量,源码中直接写出的常量值,如 0b101、3.14
Epoch / Unix time — Unix 时间点,1970-01-01 00:00:00 UTC 起的秒数
googol — 古戈尔,10 ** 100,1 后面 100 个零

7.2 运算与规则

术语 全拼 / 说明 释义
operator — 运算符
operand — 操作数,参与运算的对象
precedence — 优先级,决定多个运算符的执行次序
associativity — 结合性,同优先级时的求值方向(** 是右结合,其余多左结合)
floor division — 整除 //,向下取整
modulo — 取模 %,求余数
divmod Divide + Modulo 内建函数,一次返回 (商, 余数) 二元组
compound assignment — 复合赋值,如 +=、//=、**=
chained comparison — 链式比较,如 3 < a < 10
short-circuit — 短路求值,and/or 在确定结果后不再求后续表达式
truthy / falsy — 真值 / 假值,对象在布尔上下文中的真假判定
constant folding — 常量折叠,编译器合并同一编译单元内重复字面量的优化
small integer cache — 小整数缓存,CPython 预建 [-5, 256] 的整数对象
banker's rounding — 银行家舍入,.5 时取最近偶数,Python round() 的默认行为
walrus operator — 海象运算符 :=,Python 3.8+,赋值表达式,优先级最低

7.3 异常

术语 全拼 / 说明 释义
SyntaxError — 语法错误,编译期抛出,文件无法启动
ValueError — 值错误,类型对但值不合法,如 int('3.14')
ZeroDivisionError — 除数为 0 时抛出
OverflowError — 溢出错误(Python 3 的 int 不会触发,float 会)

8 系列导航

01_Python基础
  1. 1.Python 入门
  2. 2.编程基础概念
  3. 3.Python 中的基础数据类型
  4. 4.字符串
  5. 5.内建数据结构
  6. 6.控制语句
  7. 7.函数用法
  8. 8.面向对象编程
  9. 9.异常和错误
  10. 10.文件操作(IO 技术)
  11. 11.模块 (module)
  12. 12.正则表达式 ★★★
  13. 13.并发编程
  14. 14.网络编程
  15. 15.Python操作MySQL
相关主题
  • 位运算的实战场景:位运算的使用场景、按位异或(XOR)详解
  • 类型判断与注解:Python 类型注解详解、Python代码总出bug?学会这个typing库,让你的代码像专业程序员一样严谨!
  • 字符串与序列:4.字符串、Python 中常用的序列

9 参考链接

分类:Python

posted @ 2026-04-11 01:55  挖掘鱼  阅读(31)  评论(0)    收藏  举报