Python基础语法
Python 是一门语法简洁、适合脚本、Web、数据分析和 AI 开发的语言。它容易入门,但要写出可维护的代码,不能只背 if、for、print,还要理解:代码如何执行、变量到底是什么、类型转换为什么会失败、循环为什么会停不下来、脚本入口为什么重要。
学完本页后,你应该能做到:
- 写出一个可以直接运行的
.py脚本。 - 看懂 Python 从上到下执行文件的过程。
- 明白变量名是对象引用,不是“盒子本身”。
- 会使用字符串、数字、布尔值、空值、条件、循环。
- 能处理用户输入、文件和接口数据中的非法值。
- 能写一个带输入、校验、计算、输出的商业小 Demo。
- 能回答基础语法常见面试题。
Python 程序如何执行
运行一个 Python 文件时,解释器会读取文件,解析语法,然后按语句顺序执行。
flowchart TD
A["执行 python app.py"] --> B["启动 Python 解释器"]
B --> C["读取 app.py 源代码"]
C --> D["解析语法并生成可执行结构"]
D --> E["从文件第一行开始执行"]
E --> F{"遇到函数或类定义"}
F -->|是| G["创建函数或类对象,不自动执行业务"]
F -->|否| H["执行普通语句"]
G --> I{"是否调用 main"}
H --> I
I -->|是| J["执行业务逻辑"]
I -->|否| K["文件执行结束"]这解释了几个现象:
- 函数定义本身不会运行,只有调用函数才会执行函数体。
- 文件顶层代码会在导入时执行,所以模块里不要乱写会连接数据库、删文件、发请求的顶层逻辑。
if __name__ == "__main__"可以区分“直接运行”和“被导入”。
第一个程序
新建 hello.py:
print("hello python")运行:
python hello.pyprint() 是最常用的输出函数,初学调试时可以先用它观察变量值。商业项目里不要长期用 print 当日志,后续应学习 Python 日志与调试。
缩进表示代码块
Python 不使用 {} 表示代码块,而是使用缩进。
score = 90
if score >= 60:
print("及格")
print("继续保持")
else:
print("不及格")缩进决定代码属于哪个代码块:
flowchart TD
A["if score >= 60"] --> B["缩进的两行属于 if 分支"]
A --> C["else 与 if 对齐"]
C --> D["else 下方缩进代码属于 else 分支"]注意:
- 同一个代码块缩进必须一致。
- 推荐统一使用 4 个空格。
- 不要混用 Tab 和空格。
- 缩进不是排版问题,而是语法的一部分。
错误示例:
if True:
print("第一行")
print("第二行") # 缩进不一致,会报 IndentationError注释
单行注释:
# 计算订单总价
total = price * quantity多行说明通常使用多个 #,或者写在函数文档字符串中:
def calculate_total(price: float, quantity: int) -> float:
"""计算订单总价。"""
return price * quantity注释不是越多越好。好的变量名和函数名能减少注释;注释应解释“为什么这样做”,而不是重复代码“做了什么”。
变量的本质:名字引用对象
Python 变量不需要提前声明类型:
name = "Tom"
age = 18
active = True很多初学者会以为变量是盒子,值放在盒子里。更准确的理解是:变量名指向对象。
a = [1, 2, 3]
b = a
b.append(4)
print(a) # [1, 2, 3, 4]为什么 a 也变了?因为 a 和 b 指向同一个列表对象。
flowchart TD
A["变量名 a"] --> C["列表对象 [1, 2, 3]"]
B["变量名 b"] --> C
C --> D["b.append(4) 修改同一个对象"]数字、字符串这类不可变对象表现不同:
x = 10
y = x
y = 20
print(x) # 10这里 y = 20 不是修改整数对象,而是让 y 指向另一个整数对象。
命名规范
命名建议:
| 类型 | 推荐写法 | 示例 |
|---|---|---|
| 变量 | 小写加下划线 | user_name |
| 常量 | 大写加下划线 | MAX_RETRY_COUNT |
| 函数 | 小写加下划线 | get_user_info |
| 类 | 大驼峰 | UserService |
| 私有约定 | 单下划线开头 | _parse_row |
变量名要表达业务含义。不要写:
a = 10
b = 3
c = a * b更好:
price = 10
quantity = 3
total_amount = price * quantity基础类型
| 类型 | 示例 | 说明 | 常见场景 |
|---|---|---|---|
int | 10 | 整数 | 数量、页码、用户 ID |
float | 3.14 | 浮点数 | 比例、坐标、非精确计算 |
bool | True、False | 布尔值 | 是否启用、是否删除 |
str | "hello" | 字符串 | 名称、编码、接口字段 |
None | None | 空值 | 查询不到、未配置 |
查看类型:
price = 19.9
print(type(price))注意金额不要优先用 float:
print(0.1 + 0.2) # 0.30000000000000004商业系统里的订单金额、资产原值、支付金额建议用 Decimal:
from decimal import Decimal
price = Decimal("19.90")
quantity = 3
print(price * quantity)字符串
字符串用于保存文本。
name = "Tom"
message = f"hello {name}"
print(message)常用方法:
text = " Python,AI,Web "
print(text.strip()) # 去掉首尾空格
print(text.split(",")) # 按逗号切分
print(text.replace("AI", "LLM"))
print(text.startswith(" Py"))
print(text.lower())
print(text.upper())f-string 是推荐的字符串格式化方式:
user_name = "Tom"
score = 95
print(f"{user_name} 的分数是 {score}")格式化小数:
amount = 123.456
print(f"{amount:.2f}") # 123.46常见坑:字符串不可变。
name = "tom"
name.upper()
print(name) # tomupper() 返回新字符串,不会修改原字符串。
正确写法:
name = name.upper()输入与输出
input() 会读取用户输入,返回值永远是字符串。
age_text = input("请输入年龄:")
age = int(age_text)
print(age + 1)如果用户输入 abc,int(age_text) 会抛 ValueError。所以凡是来自用户、文件、接口的数据,都要校验。
def read_int(prompt: str) -> int:
while True:
text = input(prompt).strip()
try:
return int(text)
except ValueError:
print("请输入整数")这段代码体现了基础语法里的一个重要思想:外部输入不可信,进入业务计算前先转换和校验。
类型转换
常见转换:
age = int("18")
price = float("19.9")
text = str(100)
enabled = bool(1)转换失败:
try:
value = int("abc")
except ValueError:
print("无法转换为整数")布尔转换要特别小心:
print(bool("")) # False
print(bool("False")) # True为什么 "False" 是 True?因为非空字符串都是真值。配置项和接口参数不要直接 bool("False")。
更稳的转换:
def parse_bool(text: str) -> bool:
value = text.strip().lower()
if value in {"true", "1", "yes", "y"}:
return True
if value in {"false", "0", "no", "n"}:
return False
raise ValueError(f"非法布尔值: {text}")真值和假值
Python 中很多对象可以直接用于条件判断。
| 值 | 布尔结果 |
|---|---|
0 | False |
0.0 | False |
"" | False |
[] | False |
{} | False |
set() | False |
None | False |
| 非空字符串、非空列表、非 0 数字 | True |
示例:
users = []
if not users:
print("没有用户")注意:None 和空字符串有不同业务含义。
name = None # 没有提供
name = "" # 提供了,但是为空字符串在接口和数据清洗里,这两个含义可能不同。
条件判断
score = 88
if score >= 90:
level = "优秀"
elif score >= 60:
level = "及格"
else:
level = "不及格"
print(level)执行流程:
flowchart TD
A["进入 if"] --> B{"score >= 90"}
B -->|是| C["level = 优秀"]
B -->|否| D{"score >= 60"}
D -->|是| E["level = 及格"]
D -->|否| F["level = 不及格"]
C --> G["继续后续代码"]
E --> G
F --> G常见比较和逻辑运算:
| 运算 | 含义 |
|---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
and | 并且 |
or | 或者 |
not | 取反 |
不要这样写复杂条件:
if status == "paid" and amount > 0 and user_active and not locked and stock > 0:
...更清晰:
can_pay = status == "paid" and amount > 0
can_operate_user = user_active and not locked
has_stock = stock > 0
if can_pay and can_operate_user and has_stock:
...match case
Python 3.10+ 支持 match case,适合处理固定枚举类分支。
def status_text(status: str) -> str:
match status:
case "created":
return "已创建"
case "paid":
return "已支付"
case "cancelled":
return "已取消"
case _:
return "未知状态"如果项目使用 Python 3.9 或更低版本,不能使用 match case,应使用 if/elif 或字典映射。
for 循环
for 用来遍历可迭代对象,例如列表、字符串、字典、文件行。
names = ["Tom", "Alice", "Bob"]
for name in names:
print(name)配合 range():
for i in range(5):
print(i)输出是 0 到 4,不包含 5。
遍历时拿到下标:
names = ["Tom", "Alice", "Bob"]
for index, name in enumerate(names, start=1):
print(index, name)遍历字典:
user = {"name": "Tom", "age": 18}
for key, value in user.items():
print(key, value)while 循环
while 适合不知道循环次数、由条件控制的场景。
count = 0
while count < 5:
print(count)
count += 1如果条件永远为真,就会死循环:
while True:
print("停不下来")商业项目里 while True 不是不能用,但必须有明确退出条件、超时、最大重试次数或外部停止信号。
break、continue、else
flowchart TD
A["进入循环"] --> B{"是否还有元素或条件为真"}
B -->|否| C["正常结束循环"]
B -->|是| D["执行循环体"]
D --> E{"遇到 break"}
E -->|是| F["立即结束循环"]
E -->|否| G{"遇到 continue"}
G -->|是| B
G -->|否| B示例:
for num in range(1, 6):
if num == 3:
continue
if num == 5:
break
print(num)continue 跳过本次循环,break 直接结束循环。
循环也可以带 else,表示循环没有被 break 中断时执行:
target = 8
for num in [1, 3, 5]:
if num == target:
print("找到了")
break
else:
print("没找到")这个写法不算常用,但在查找场景中很清晰。
列表和字典快速入门
列表保存一组有序数据:
users = ["Tom", "Alice"]
users.append("Bob")
print(users[0])字典保存键值对:
user = {
"name": "Tom",
"age": 18,
}
print(user["name"])
print(user.get("email", "未填写"))更多内容见 Python 数据结构。
这里先记住:
| 结构 | 适合场景 |
|---|---|
list | 有序列表,例如多条订单、多行 CSV |
dict | key-value,例如一个用户、一条资产 |
set | 去重和快速判断存在 |
tuple | 固定结构,不希望轻易修改 |
函数快速入门
函数用于封装可复用逻辑。
def calculate_average(scores: list[int]) -> float:
if not scores:
return 0.0
return sum(scores) / len(scores)调用:
average = calculate_average([90, 80, 70])
print(f"{average:.2f}")函数的价值:
- 让一段逻辑有名字。
- 减少重复代码。
- 方便测试。
- 让主流程更清晰。
更多内容见 Python 函数与模块。
main 入口
def main():
print("执行主逻辑")
if __name__ == "__main__":
main()这段代码表示:
- 文件被直接运行时,执行
main()。 - 文件被其他模块导入时,不自动执行
main()。
流程:
flowchart TD
A["Python 执行文件"] --> B{"__name__ 是否等于 __main__"}
B -->|是| C["说明文件被直接运行"]
C --> D["调用 main"]
B -->|否| E["说明文件被其他模块导入"]
E --> F["只提供函数和类,不执行业务入口"]如果不写入口判断,别人导入你的函数时,脚本里的业务逻辑也可能被执行。
商业 Demo:订单金额计算脚本
需求:编写一个命令行脚本,输入商品单价、数量、折扣、是否会员,输出订单应付金额。要求:
- 单价必须大于等于 0。
- 数量必须大于 0。
- 折扣范围是 0 到 1。
- 会员额外减 5%。
- 输入非法时提示用户重新输入。
完整 Demo:
from decimal import Decimal, InvalidOperation
def read_decimal(prompt: str) -> Decimal:
while True:
text = input(prompt).strip()
try:
return Decimal(text)
except InvalidOperation:
print("请输入合法数字,例如 19.90")
def read_int(prompt: str) -> int:
while True:
text = input(prompt).strip()
try:
return int(text)
except ValueError:
print("请输入整数,例如 3")
def read_bool(prompt: str) -> bool:
while True:
text = input(prompt).strip().lower()
if text in {"y", "yes", "true", "1"}:
return True
if text in {"n", "no", "false", "0"}:
return False
print("请输入 y 或 n")
def calculate_pay_amount(
price: Decimal,
quantity: int,
discount: Decimal,
is_member: bool,
) -> Decimal:
if price < 0:
raise ValueError("单价不能小于 0")
if quantity <= 0:
raise ValueError("数量必须大于 0")
if discount < 0 or discount > 1:
raise ValueError("折扣必须在 0 到 1 之间")
amount = price * quantity * discount
if is_member:
amount = amount * Decimal("0.95")
return amount.quantize(Decimal("0.01"))
def main():
price = read_decimal("请输入单价:")
quantity = read_int("请输入数量:")
discount = read_decimal("请输入折扣,例如 0.8:")
is_member = read_bool("是否会员 y/n:")
try:
pay_amount = calculate_pay_amount(price, quantity, discount, is_member)
except ValueError as exc:
print(f"计算失败:{exc}")
return
print(f"应付金额:{pay_amount} 元")
if __name__ == "__main__":
main()执行流程:
flowchart TD
A["启动脚本"] --> B["读取单价"]
B --> C["读取数量"]
C --> D["读取折扣"]
D --> E["读取是否会员"]
E --> F["校验业务规则"]
F --> G{"是否合法"}
G -->|否| H["输出错误并结束"]
G -->|是| I["计算原始金额"]
I --> J{"是否会员"}
J -->|是| K["额外 95 折"]
J -->|否| L["不额外折扣"]
K --> M["保留两位小数"]
L --> M
M --> N["输出应付金额"]这个 Demo 把基础语法串起来了:
| 语法点 | 在 Demo 中的作用 |
|---|---|
| 变量 | 保存单价、数量、折扣 |
| 类型转换 | 把输入字符串转成 Decimal、int、bool |
| 条件判断 | 判断会员、判断非法参数 |
| 循环 | 输入错误时重复提示 |
| 函数 | 拆分读取、转换、计算逻辑 |
| 异常 | 处理转换失败和业务校验失败 |
| main 入口 | 让脚本可运行也可导入测试 |
常见错误和排查
| 错误 | 示例 | 原因 | 解决 |
|---|---|---|---|
IndentationError | 缩进不一致 | Python 用缩进表示代码块 | 统一 4 空格 |
NameError | 使用未定义变量 | 当前作用域找不到名字 | 检查变量是否先赋值 |
TypeError | "1" + 2 | 类型不兼容 | 先做类型转换 |
ValueError | int("abc") | 值格式不合法 | 捕获异常并提示 |
IndexError | users[10] | 下标越界 | 访问前检查长度 |
KeyError | user["email"] | 字典没有这个 key | 用 get() 或先判断 |
| 死循环 | while True 无退出 | 条件永远成立 | 加退出条件、最大次数 |
排查思路:
flowchart TD
A["程序报错"] --> B["先看错误类型"]
B --> C["再看文件名和行号"]
C --> D["看报错行使用了哪些变量"]
D --> E["打印 type 和 value"]
E --> F["确认输入、类型转换、分支是否符合预期"]面试标准回答
Python 变量的本质是什么?
标准回答:Python 变量本质上是名字对对象的引用。赋值不是把值复制进盒子,而是让变量名指向某个对象。多个变量可以指向同一个可变对象,所以修改列表、字典这类可变对象时,其他引用也能看到变化。
Python 为什么用缩进?
标准回答:Python 用缩进表示代码块,缩进是语法的一部分,不只是格式。这样代码结构更统一,但要求同一代码块缩进一致,不能混用 Tab 和空格。
is 和 == 有什么区别?
标准回答:== 比较两个对象的值是否相等,is 比较两个变量是否引用同一个对象。判断是否为 None 时应该用 is None,普通值比较通常用 ==。
a = [1, 2]
b = [1, 2]
print(a == b) # True
print(a is b) # Falseif not value 会判断哪些情况?
标准回答:if not value 会把空字符串、空列表、空字典、空集合、数字 0、None 都当成假值。它适合判断“是否为空”,但如果业务上要区分 None 和空字符串,就不能简单使用 if not value。
为什么 input 得到的是字符串?
标准回答:用户输入来自终端文本流,Python 无法知道用户想要整数、小数还是布尔值,所以 input() 永远返回字符串。业务使用前要根据需要转换,并处理转换失败。
为什么金额不建议用 float?
标准回答:float 是二进制浮点数,很多十进制小数无法精确表示,例如 0.1 + 0.2 结果不是严格的 0.3。订单、支付、资产金额这类精确小数应使用 Decimal。
__name__ == "__main__" 的作用是什么?
标准回答:它用于判断文件是被直接运行还是被其他模块导入。直接运行时 __name__ 等于 "__main__",可以调用 main();被导入时不执行业务入口,避免导入模块产生副作用。
练习
- 写一个脚本,输入分数后输出优秀、及格、不及格。
- 遍历 1 到 100,打印所有偶数。
- 定义一个用户字典,安全读取不存在的
email字段。 - 写一个函数计算列表平均值,空列表返回 0。
- 把脚本逻辑放入
main(),并使用入口判断。 - 扩展订单金额 Demo:增加满 100 减 10 的优惠。
- 故意输入非法单价,观察错误如何被处理。
关联知识点
- Python 环境与包管理:学习如何创建虚拟环境和运行脚本。
- Python 数据结构:深入理解
list、dict、set。 - Python 函数与模块:把脚本拆成可维护的函数和模块。
- Python 异常与文件:处理输入转换、文件读取、CSV/JSON 错误。
- Python 类型标注:给函数参数和返回值写清楚类型契约。
小结
Python 基础语法的重点不是写得短,而是写得清楚、可运行、可排查。变量是对象引用,缩进决定代码块,外部输入必须校验,循环必须有退出条件,金额计算要注意精度,脚本要有 main 入口。真正掌握这些基础后,再学习数据结构、函数模块、文件、Web、AI 才会顺畅。
