🔥 星光编译者 · 个人主页
📚 学习专栏: 《C/C++ 成长笔记》 · 《Linux 实践手册》 · 《数据结构与算法》
🌄 向云端飞扬,编译属于自己的代码星河。
☕ 写在开篇
你好,这里是 星光编译者。
这里记录我在 C/C++、Linux、数据结构与算法 学习中遇到的真实问题、亲手验证过的代码,以及那些容易被忽略的实现细节。
比起简单罗列结论,我更愿意从问题出发,把一个知识点的来由讲清楚,把"为什么会这样"和"应该怎样解决"说明白,让每一次踩坑都沉淀成可以复用的经验。
如果这篇记录能帮你少绕一点路,或让某个模糊的地方忽然变得清晰,那么这次分享便有了意义。愿我们在一次次阅读、编译与调试中稳步向前,慢慢搭起属于自己的技术世界。

🔥 本文定位:面向 Python 初学者,从"把 Python 当计算器"开始,建立表达式、变量、数据类型、控制台交互与运算符的完整认知。
💡 学习目标 :能读懂并写出基本表达式;理解变量绑定和动态类型;会使用
input()、print()与 f-string;掌握算术、关系、逻辑和赋值运算符;能避开浮点数精度、字符串拼接与短路求值中的常见坑。📌 阅读说明 :本文根据课程 PDF《2.基础语法(1)》整理,并按现代 Python 3 实践补充
snake_case、math.isclose()、异常处理与 docstring 的准确语义。
文章目录
- 一、从计算器开始:常量、运算符与表达式
- 二、变量的本质:不只是"存数据的盒子"
- 三、基本类型与动态类型
- 四、注释与文档字符串
- 五、控制台输入输出
- 六、算术运算符
- 七、关系运算符与浮点数比较
- 八、逻辑运算符与短路求值
- 九、赋值、拆包、复合赋值与交换
- 十、综合实战:一个更稳健的成绩计算器
- 十一、常见误区与自测练习
- 总结
一、从计算器开始:常量、运算符与表达式
Python 可以直接完成算术计算:
python
print(1 + 2 - 3)
print(1 + 2 * 3)
print((1 + 2) * 3)
print(1 + 2 / 3)
这四行代码虽然简单,却已经包含三个基本概念:
1、2、3是直接写在代码里的字面值;+、-、*、/是运算符;- 字面值与运算符按规则组合成表达式,求值后产生一个结果。

1.1 优先级与括号
Python 的基本算术优先级与数学习惯一致:先乘除,后加减,括号最先。因此:
python
1 + 2 * 3 # 7
(1 + 2) * 3 # 9
当表达式稍微复杂时,即使默认优先级恰好符合意图,也可以用括号强化可读性。不要把代码写成一场"运算符优先级背诵比赛"。
1.2 / 不会截断小数
在 Python 3 中,/ 执行真除法:
python
print(2 / 3) # 0.6666666666666666
print(4 / 2) # 2.0
即使两边都是整数,/ 的结果也是 float。如果需要地板除,应使用 //,但它对负数的行为与"直接去掉小数"不同,后文会专门说明。
1.3 用表达式计算平均数
python
average = (67.5 + 89.0 + 12.9 + 32.2) / 4
print(average)
这里的右侧是表达式,左侧的 average 则把结果保留了下来。一旦计算需要多个中间步骤,变量就开始显示价值。
二、变量的本质:不只是"存数据的盒子"
初学时常把变量比喻成"存放数据的盒子"。这个比喻有助于入门,但对 Python 而言,更准确的理解是:
变量是一个名字,赋值会让这个名字与某个对象建立绑定。
python
score = 89.5
score = "A"
第一行让 score 绑定到一个 float 对象;第二行又让它改为绑定一个 str 对象。不是"原来的浮点数盒子被改造成了字符串盒子",而是名字的指向发生了变化。

2.1 变量的定义、读取与修改
python
count = 10 # 首次绑定
print(count) # 读取
count = 20 # 重新绑定
print(count)
Python 不需要在变量名前写 int、float 之类的类型声明。变量必须先赋值再使用:
python
# print(total) # NameError: name 'total' is not defined
2.2 变量名的硬性规则
合法变量名需要满足:
- 由字母、数字和下划线组成;
- 不能以数字开头;
- 不能与 Python 关键字重复;
- 区分大小写,
score与Score是两个名字。
python
user_name = "Ada" # 合法
score2 = 95 # 合法
_cache = {} # 合法
# 2score = 95 # 非法:数字开头
# class = "A" # 非法:class 是关键字
可以用标准库查看关键字:
python
import keyword
print(keyword.kwlist)
2.3 软性规范:优先使用 snake_case
变量名要表达用途,不要满篇都是 a、b、x、y。现代 Python 代码通常遵循 PEP 8,变量和函数名推荐使用小写加下划线:
python
total_count = 100
person_info = "student"
average_score = 86.5
totalCount 这种驼峰写法并非语法错误,但它不是 Python 变量名的主流风格。
三、基本类型与动态类型
类型并不是为了给知识点分类而硬造出来的名词。它至少回答两个问题:
- 这个对象如何在计算机中表示?
- 可以对它执行哪些操作?

3.1 int:整数
python
count = 42
print(type(count)) # <class 'int'>
Python 的 int 不固定为 32 位或 64 位整数,数值可在内存和实现允许的范围内继续增大:
python
huge_number = 10 ** 100
print(huge_number)
"任意精度"不等于物理世界中的"无限";实际能表示多大仍受内存和运行环境限制。
3.2 float:浮点数
python
temperature = 36.5
print(type(temperature)) # <class 'float'>
Python 内置的 float 通常使用 IEEE 754 双精度表示。它能表示很大的范围,但并不能精确表示所有十进制小数。
3.3 str:字符串
python
language = "Python"
message = 'hello'
print(len(language)) # 6
print(message + " world") # hello world
单引号与双引号创建的都是 str,Python 没有独立的"单字符类型";"A" 仍然是长度为 1 的字符串。
python
print(type("A")) # <class 'str'>
字符串可以与字符串拼接,却不能直接与整数相加:
python
age = 18
print("age = " + str(age)) # 可以,但更推荐 f-string
print(f"age = {age}")
# print("age = " + age) # TypeError
3.4 bool:布尔值
python
is_ready = True
is_finished = False
True 和 False 的首字母必须大写。从类型关系上说,bool 是 int 的子类,所以:
python
print(True + 1) # 2
print(False + 1) # 1
这个行为在计数场景中偶尔有用,但不要为了"省一行代码"而让业务含义变得难懂。
3.5 动态类型是一把双刃剑
python
value = 10
print(type(value)) # int
value = "ten"
print(type(value)) # str
好处是代码简洁、函数容易复用;代价是错误可能到运行时才出现。大型项目中可以通过清晰命名、单元测试、类型标注和静态检查降低沟通成本:
python
def calculate_average(total: float, count: int) -> float:
return total / count
类型标注主要服务于阅读与工具检查,Python 默认不会因为标注而自动在运行时强制类型。
四、注释与文档字符串
代码首先要能被人读懂,然后才是让计算机执行。注释的价值不在于"多",而在于它能否解释代码本身无法直接表达的意图、边界与取舍。

4.1 单行注释
# 之后到行尾的内容是注释:
python
# 样本方差的分母使用 n - 1
variance = squared_error_sum / (sample_count - 1)
上面的注释说明了"为什么是 n - 1",比"计算方差"更有信息量。
4.2 docstring 不只是多行注释
三引号可以创建多行字符串。当它作为模块、函数、类或方法的第一条语句时,会成为文档字符串:
python
def average(a: float, b: float) -> float:
"""返回两个数的算术平均值。"""
return (a + b) / 2
print(average.__doc__)
它是一个真实的字符串对象,可被 help()、IDE 和文档生成工具使用。因此,不应把"任意位置写一个三引号字符串"当成 Python 的通用多行注释语法。
4.3 注释的四个检查点
- 准确:代码改了,注释也要改;
- 适量:既不写废话,也不留下无法理解的黑盒;
- 解释意图:多回答"为什么",少重复"做了什么";
- 专业:把注释视为团队文档,避免情绪化和攻击性内容。
五、控制台输入输出
用户向程序提供信息是输入 ,程序向用户展示结果是输出。图形界面、Web 页面和 API 都是交互方式,但学习阶段最直接的入口是控制台。

5.1 print() 输出
python
name = "Ada"
age = 18
print("hello")
print(name)
print("name =", name, "age =", age)
print() 可以接收多个参数,默认用空格分隔,并在最后换行。可以通过 sep 和 end 修改:
python
print("2026", "09", "24", sep="-") # 2026-09-24
print("loading", end="...")
print("done") # loading...done
5.2 f-string:把值放进字符串
python
name = "Ada"
score = 96.5
print(f"{name} 的成绩是 {score}")
print(f"成绩保留一位小数:{score:.1f}")
{} 中可以放变量,也可以放简单表达式:
python
price = 19.9
count = 3
print(f"合计:{price * count:.2f} 元")
5.3 input() 的返回值永远是字符串
python
age = input("请输入年龄:")
print(type(age)) # str
因此,下面的代码做的是拼接,不是数学加法:
python
a = input("请输入 a:") # 输入 10
b = input("请输入 b:") # 输入 20
print(a + b) # 1020
需要先转换类型:
python
a = int(input("请输入 a:"))
b = int(input("请输入 b:"))
print(a + b) # 30
5.4 类型转换不一定成功
python
# int("hello") # ValueError
当输入不可信时,应使用异常处理:
python
try:
age = int(input("请输入年龄:"))
except ValueError:
print("输入无效,请输入整数。")
else:
print(f"明年你将 {age + 1} 岁。")
还有一个非常容易被忽略的点:
python
print(bool("False")) # True
print(bool("")) # False
bool() 对字符串判断的是"是否为空",不会识别单词"False"的语义。
六、算术运算符
Python 常用算术运算符包括 +、-、*、/、%、**、//。

| 运算符 | 含义 | 示例 | 结果 |
|---|---|---|---|
+ |
加法,也可用于字符串拼接 | 7 + 2 |
9 |
- |
减法 | 7 - 2 |
5 |
* |
乘法,也可用于序列重复 | "ha" * 3 |
"hahaha" |
/ |
真除法 | 7 / 2 |
3.5 |
// |
地板除 | 7 // 2 |
3 |
% |
取余 | 7 % 2 |
1 |
** |
幂运算 | 4 ** 2 |
16 |
6.1 除数不能为 0
python
# print(10 / 0) # ZeroDivisionError
除零错误不是程序"有点不准",而是当前计算无法继续,Python 会抛出异常。
6.2 // 是向下取整
python
print(7 // 2) # 3
print(-7 // 2) # -4
print(int(-7 / 2)) # -3
-7 / 2 是 -3.5。// 向负无穷方向取整,所以得到 -4;int() 对浮点数转整数时则向 0 截断,所以得到 -3。两者不能混为一谈。
6.3 % 与取整方向配合
Python 满足这个关系:
text
a == (a // b) * b + (a % b)
因此:
python
print(-7 // 2) # -4
print(-7 % 2) # 1
# -7 == (-4) * 2 + 1
当负数参与取模时,不要只靠直觉猜结果,应回到上面的等式检查。
6.4 ** 不只能算整数次方
python
print(4 ** 2) # 16
print(4 ** 0.5) # 2.0
对负数底数进行非整数次幂运算时,结果还可能进入复数范围:
python
print((-1) ** 0.5) # 近似为 1j
七、关系运算符与浮点数比较
关系运算符用来比较两个值,返回布尔结果:
python
a = 10
b = 20
print(a < b) # True
print(a <= b) # True
print(a > b) # False
print(a >= b) # False
print(a == b) # False
print(a != b) # True
= 是赋值,== 才是相等比较。
7.1 字符串按字典序比较
python
print("apple" < "banana") # True
print("Zoo" < "apple") # True
字符串比较是逐个字符按 Unicode 码点进行,它不等同于自然语言中面向用户的排序规则。大小写、重音符号和语言区域都可能影响期望结果。
7.2 链式比较
Python 可以直接写出贴近数学习惯的范围判断:
python
age = 25
print(18 <= age < 60)
它等价于对中间值只求值一次的链式比较,语义接近:
python
18 <= age and age < 60
7.3 浮点数不宜直接用 ==
python
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False
这不是 Python 的算术出错,而是许多十进制小数无法被有限位二进制浮点数精确表示。

不要只写一个神秘的固定差值,标准库的 math.isclose() 同时支持相对容差与绝对容差:
python
import math
a = 0.1 + 0.2
b = 0.3
print(math.isclose(a, b))
print(math.isclose(a, b, rel_tol=1e-9, abs_tol=0.0))
如果比较的量可能接近 0,绝对容差往往也很重要:
python
print(math.isclose(1e-12, 0.0, abs_tol=1e-9)) # True
容差应来自业务允许的误差范围,而不是为了"让测试通过"随意调大。金额等需要精确十进制语义的场景,通常应考虑 decimal.Decimal。
八、逻辑运算符与短路求值
Python 的逻辑运算符为 and、or、not:
A and B:只有两者都为真时整体才为真;A or B:只要至少一个为真,整体就为真;not A:对真值取反。
python
age = 25
has_ticket = True
print(age >= 18 and has_ticket)
print(age < 18 or not has_ticket)
8.1 短路求值

对 and 而言,左边为假时,整体已经不可能为真,因此右边不再执行。对 or 而言,左边为真时,整体已经确定为真,右边也不再执行。
python
print(False and 10 / 0) # False,右侧未执行
print(True or 10 / 0) # True,右侧未执行
短路常用于安全前置检查:
python
denominator = 0
if denominator != 0 and 10 / denominator > 2:
print("条件成立")
第一个条件为假后,除法不会执行,从而避免除零。
8.2 and 和 or 返回的不一定是 bool
这是从"会用"到"真正理解"的一个重要细节。and 与 or 返回的是决定结果的那个操作数:
python
print("" or "guest") # guest
print("Ada" and "online") # online
print(0 and 100) # 0
Python 会对对象进行真值测试。常见假值包括 False、None、数字 0、空字符串与空容器。这种写法可用于默认值,但要小心把合法的 0 或空字符串也当成"缺失"。
九、赋值、拆包、复合赋值与交换
= 表示赋值,它按先右后左的思路工作:先计算右侧表达式,再把结果绑定给左侧名字。

9.1 链式赋值
python
a = b = 10
a 与 b 会绑定到同一个整数对象。对整数这类不可变对象,通常很直观;对列表等可变对象则要特别小心:
python
a = b = []
a.append(1)
print(b) # [1]
这不是 b "偷看了" a,而是两个名字从一开始就绑定到同一个列表。
9.2 多元赋值与拆包
python
name, age = "Ada", 18
print(name)
print(age)
左右数量应匹配,否则会触发 ValueError:
python
# a, b = 1, 2, 3 # too many values to unpack
9.3 交换变量
python
a = 10
b = 20
a, b = b, a
print(a, b) # 20 10
可以概念上理解为:先取得右侧 b 和 a 的值,再按位置分别绑定给左侧 a 和 b,所以不需要手写临时变量。
9.4 复合赋值
python
count = 10
count += 1
count *= 2
print(count) # 22
Python 支持 +=、-=、*=、/=、//=、%=、**= 等复合赋值,但不支持 C/C++/Java 中的 ++ 和 --:
python
count += 1 # 正确
# count++ # SyntaxError
值得注意的是,对可变对象而言,+= 可能就地修改原对象;它不能在所有类型上简单当成 x = x + y 的完全等价文本替换。
十、综合实战:一个更稳健的成绩计算器
现在把变量、类型转换、输入输出、算术运算、关系运算和逻辑运算组合起来。目标是:读取 4 门课成绩,验证范围,计算平均分,并输出是否合格。
python
try:
chinese = float(input("请输入语文成绩:"))
math_score = float(input("请输入数学成绩:"))
english = float(input("请输入英语成绩:"))
python_score = float(input("请输入 Python 成绩:"))
except ValueError:
print("输入无效:成绩必须是数字。")
else:
all_valid = (
0 <= chinese <= 100
and 0 <= math_score <= 100
and 0 <= english <= 100
and 0 <= python_score <= 100
)
if not all_valid:
print("输入无效:每门成绩必须在 0 到 100 之间。")
else:
total = chinese + math_score + english + python_score
average = total / 4
passed = average >= 60
print(f"总分:{total:.1f}")
print(f"平均分:{average:.2f}")
print(f"结果:{'合格' if passed else '不合格'}")
这段代码体现了一条清晰的数据处理链路:
input()获得字符串;float()尝试转换,失败时进入except;- 用链式比较和
and验证范围; - 用算术表达式计算总分和平均分;
- 用 f-string 格式化输出。
初学阶段重复写 4 次输入是为了突出当前语法知识。学习列表、循环和函数后,应把这段代码重构为更易扩展的形式。
十一、常见误区与自测练习
11.1 高频误区
误区一:把 = 当成相等比较
= 是赋值,== 是比较。a = 10 是让名字 a 绑定到数值 10,不是在做数学命题。
误区二:认为 input() 会自动识别数字
input() 返回 str。输入 10 不等于得到整数 10,算术计算前要用 int() 或 float() 转换。
误区三:认为 bool("False") 是 False
非空字符串的真值是 True。如果要解析用户输入的布尔文本,应显式定义可接受的词汇:
python
raw = input("是否继续?(y/n) :").strip().lower()
should_continue = raw in {"y", "yes"}
误区四:对浮点计算结果直接用 ==
浮点误差是表示方式的结果。近似比较优先使用 math.isclose(),精确十进制业务要考虑 Decimal。
误区五:把 // 理解成单纯删掉小数部分
// 向负无穷取整,因此 -7 // 2 是 -4,不是 -3。
误区六:把三引号等同于通用多行注释
三引号创建字符串。放在模块、函数或类的开头时它是 docstring,会被工具与运行时元数据使用,并非普通注释。
误区七:认为 and 与 or 永远返回 True 或 False
它们根据真值测试决定是否继续,并返回其中一个操作数。需要布尔值时可显式使用 bool()。
11.2 自测题
1 + 2 * 3和(1 + 2) * 3分别得到什么?- 为什么
input()读取的"10"与"20"相加得到"1020"? int、float、str、bool各适合表示什么数据?-7 // 2与int(-7 / 2)分别是多少?- 为什么
0.1 + 0.2 == 0.3是False?推荐如何比较? False and 10 / 0为什么不会抛出除零异常?a = b = []后执行a.append(1),b是什么?为什么?bool("False")的结果是什么?a, b = b, a为什么可以交换两个变量?- Python 为什么不支持
++?应怎样写自增 1?
11.3 参考答案
- 分别是
7和9,括号改变了求值顺序。 - 因为
input()返回str,+对两个字符串表示拼接。 - 依次是整数、浮点数、文本字符序列、真假状态。
- 分别是
-4和-3;前者向下取整,后者向 0 截断。 - 许多十进制小数无法用有限位二进制浮点数精确表示;推荐使用
math.isclose()并设置业务合理的容差。 and发生短路,左侧为假后右侧不再执行。b也是[1],因为a与b绑定到同一个可变列表。True,因为它是非空字符串。- 概念上先对右侧求值,再按位置将结果绑定给左侧名字。
- Python 没有前置/后置自增运算符,直接写
value += 1。
总结
这一讲的知识点看起来很多,但可以收束成一条稳定的主线:
- 字面值提供数据,运算符把数据组成表达式;
- 变量是名字与对象的绑定,而不是固定类型的物理盒子;
- 类型决定表示与操作 ,
int、float、str、bool的规则不能随意混用; input()返回字符串,转换类型时要考虑失败;- 运算符不只是符号,还包含优先级、类型规则、取整方向和短路语义;
- 浮点数是近似表示,工程比较需要合理容差。
真正值得掌握的,不是每个符号孤立的读法,而是面对一行代码时能够按顺序问出:数据是什么类型?表达式按什么顺序求值?中间会不会转换、舍入或短路?最终又把结果绑定到哪个名字?
把这条思考链建立起来,后面学习条件、循环、函数和容器时,语法就不会再是零散的记忆点。
🔥 如果这篇文章对你有帮助,欢迎点赞、收藏与关注。
📚 下一篇继续学习 Python 的条件判断与循环结构。