Skip to content

Python基础语法

Python 是一门语法简洁、适合脚本、Web、数据分析和 AI 开发的语言。它容易入门,但要写出可维护的代码,不能只背 ifforprint,还要理解:代码如何执行、变量到底是什么、类型转换为什么会失败、循环为什么会停不下来、脚本入口为什么重要。

学完本页后,你应该能做到:

  1. 写出一个可以直接运行的 .py 脚本。
  2. 看懂 Python 从上到下执行文件的过程。
  3. 明白变量名是对象引用,不是“盒子本身”。
  4. 会使用字符串、数字、布尔值、空值、条件、循环。
  5. 能处理用户输入、文件和接口数据中的非法值。
  6. 能写一个带输入、校验、计算、输出的商业小 Demo。
  7. 能回答基础语法常见面试题。

Python 程序如何执行

运行一个 Python 文件时,解释器会读取文件,解析语法,然后按语句顺序执行。

mermaid
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["文件执行结束"]

这解释了几个现象:

  1. 函数定义本身不会运行,只有调用函数才会执行函数体。
  2. 文件顶层代码会在导入时执行,所以模块里不要乱写会连接数据库、删文件、发请求的顶层逻辑。
  3. if __name__ == "__main__" 可以区分“直接运行”和“被导入”。

第一个程序

新建 hello.py

python
print("hello python")

运行:

bash
python hello.py

print() 是最常用的输出函数,初学调试时可以先用它观察变量值。商业项目里不要长期用 print 当日志,后续应学习 Python 日志与调试

缩进表示代码块

Python 不使用 {} 表示代码块,而是使用缩进。

python
score = 90

if score >= 60:
    print("及格")
    print("继续保持")
else:
    print("不及格")

缩进决定代码属于哪个代码块:

mermaid
flowchart TD
    A["if score >= 60"] --> B["缩进的两行属于 if 分支"]
    A --> C["else 与 if 对齐"]
    C --> D["else 下方缩进代码属于 else 分支"]

注意:

  1. 同一个代码块缩进必须一致。
  2. 推荐统一使用 4 个空格。
  3. 不要混用 Tab 和空格。
  4. 缩进不是排版问题,而是语法的一部分。

错误示例:

python
if True:
    print("第一行")
  print("第二行")  # 缩进不一致,会报 IndentationError

注释

单行注释:

python
# 计算订单总价
total = price * quantity

多行说明通常使用多个 #,或者写在函数文档字符串中:

python
def calculate_total(price: float, quantity: int) -> float:
    """计算订单总价。"""
    return price * quantity

注释不是越多越好。好的变量名和函数名能减少注释;注释应解释“为什么这样做”,而不是重复代码“做了什么”。

变量的本质:名字引用对象

Python 变量不需要提前声明类型:

python
name = "Tom"
age = 18
active = True

很多初学者会以为变量是盒子,值放在盒子里。更准确的理解是:变量名指向对象。

python
a = [1, 2, 3]
b = a
b.append(4)
print(a)  # [1, 2, 3, 4]

为什么 a 也变了?因为 ab 指向同一个列表对象。

mermaid
flowchart TD
    A["变量名 a"] --> C["列表对象 [1, 2, 3]"]
    B["变量名 b"] --> C
    C --> D["b.append(4) 修改同一个对象"]

数字、字符串这类不可变对象表现不同:

python
x = 10
y = x
y = 20
print(x)  # 10

这里 y = 20 不是修改整数对象,而是让 y 指向另一个整数对象。

命名规范

命名建议:

类型推荐写法示例
变量小写加下划线user_name
常量大写加下划线MAX_RETRY_COUNT
函数小写加下划线get_user_info
大驼峰UserService
私有约定单下划线开头_parse_row

变量名要表达业务含义。不要写:

python
a = 10
b = 3
c = a * b

更好:

python
price = 10
quantity = 3
total_amount = price * quantity

基础类型

类型示例说明常见场景
int10整数数量、页码、用户 ID
float3.14浮点数比例、坐标、非精确计算
boolTrueFalse布尔值是否启用、是否删除
str"hello"字符串名称、编码、接口字段
NoneNone空值查询不到、未配置

查看类型:

python
price = 19.9
print(type(price))

注意金额不要优先用 float

python
print(0.1 + 0.2)  # 0.30000000000000004

商业系统里的订单金额、资产原值、支付金额建议用 Decimal

python
from decimal import Decimal

price = Decimal("19.90")
quantity = 3
print(price * quantity)

字符串

字符串用于保存文本。

python
name = "Tom"
message = f"hello {name}"
print(message)

常用方法:

python
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 是推荐的字符串格式化方式:

python
user_name = "Tom"
score = 95
print(f"{user_name} 的分数是 {score}")

格式化小数:

python
amount = 123.456
print(f"{amount:.2f}")  # 123.46

常见坑:字符串不可变。

python
name = "tom"
name.upper()
print(name)  # tom

upper() 返回新字符串,不会修改原字符串。

正确写法:

python
name = name.upper()

输入与输出

input() 会读取用户输入,返回值永远是字符串。

python
age_text = input("请输入年龄:")
age = int(age_text)
print(age + 1)

如果用户输入 abcint(age_text) 会抛 ValueError。所以凡是来自用户、文件、接口的数据,都要校验。

python
def read_int(prompt: str) -> int:
    while True:
        text = input(prompt).strip()
        try:
            return int(text)
        except ValueError:
            print("请输入整数")

这段代码体现了基础语法里的一个重要思想:外部输入不可信,进入业务计算前先转换和校验。

类型转换

常见转换:

python
age = int("18")
price = float("19.9")
text = str(100)
enabled = bool(1)

转换失败:

python
try:
    value = int("abc")
except ValueError:
    print("无法转换为整数")

布尔转换要特别小心:

python
print(bool(""))       # False
print(bool("False"))  # True

为什么 "False"True?因为非空字符串都是真值。配置项和接口参数不要直接 bool("False")

更稳的转换:

python
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 中很多对象可以直接用于条件判断。

布尔结果
0False
0.0False
""False
[]False
{}False
set()False
NoneFalse
非空字符串、非空列表、非 0 数字True

示例:

python
users = []
if not users:
    print("没有用户")

注意:None 和空字符串有不同业务含义。

python
name = None  # 没有提供
name = ""    # 提供了,但是为空字符串

在接口和数据清洗里,这两个含义可能不同。

条件判断

python
score = 88

if score >= 90:
    level = "优秀"
elif score >= 60:
    level = "及格"
else:
    level = "不及格"

print(level)

执行流程:

mermaid
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取反

不要这样写复杂条件:

python
if status == "paid" and amount > 0 and user_active and not locked and stock > 0:
    ...

更清晰:

python
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,适合处理固定枚举类分支。

python
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 用来遍历可迭代对象,例如列表、字符串、字典、文件行。

python
names = ["Tom", "Alice", "Bob"]

for name in names:
    print(name)

配合 range()

python
for i in range(5):
    print(i)

输出是 0 到 4,不包含 5。

遍历时拿到下标:

python
names = ["Tom", "Alice", "Bob"]
for index, name in enumerate(names, start=1):
    print(index, name)

遍历字典:

python
user = {"name": "Tom", "age": 18}
for key, value in user.items():
    print(key, value)

while 循环

while 适合不知道循环次数、由条件控制的场景。

python
count = 0

while count < 5:
    print(count)
    count += 1

如果条件永远为真,就会死循环:

python
while True:
    print("停不下来")

商业项目里 while True 不是不能用,但必须有明确退出条件、超时、最大重试次数或外部停止信号。

break、continue、else

mermaid
flowchart TD
    A["进入循环"] --> B{"是否还有元素或条件为真"}
    B -->|否| C["正常结束循环"]
    B -->|是| D["执行循环体"]
    D --> E{"遇到 break"}
    E -->|是| F["立即结束循环"]
    E -->|否| G{"遇到 continue"}
    G -->|是| B
    G -->|否| B

示例:

python
for num in range(1, 6):
    if num == 3:
        continue
    if num == 5:
        break
    print(num)

continue 跳过本次循环,break 直接结束循环。

循环也可以带 else,表示循环没有被 break 中断时执行:

python
target = 8

for num in [1, 3, 5]:
    if num == target:
        print("找到了")
        break
else:
    print("没找到")

这个写法不算常用,但在查找场景中很清晰。

列表和字典快速入门

列表保存一组有序数据:

python
users = ["Tom", "Alice"]
users.append("Bob")
print(users[0])

字典保存键值对:

python
user = {
    "name": "Tom",
    "age": 18,
}

print(user["name"])
print(user.get("email", "未填写"))

更多内容见 Python 数据结构

这里先记住:

结构适合场景
list有序列表,例如多条订单、多行 CSV
dictkey-value,例如一个用户、一条资产
set去重和快速判断存在
tuple固定结构,不希望轻易修改

函数快速入门

函数用于封装可复用逻辑。

python
def calculate_average(scores: list[int]) -> float:
    if not scores:
        return 0.0
    return sum(scores) / len(scores)

调用:

python
average = calculate_average([90, 80, 70])
print(f"{average:.2f}")

函数的价值:

  1. 让一段逻辑有名字。
  2. 减少重复代码。
  3. 方便测试。
  4. 让主流程更清晰。

更多内容见 Python 函数与模块

main 入口

python
def main():
    print("执行主逻辑")


if __name__ == "__main__":
    main()

这段代码表示:

  1. 文件被直接运行时,执行 main()
  2. 文件被其他模块导入时,不自动执行 main()

流程:

mermaid
flowchart TD
    A["Python 执行文件"] --> B{"__name__ 是否等于 __main__"}
    B -->|是| C["说明文件被直接运行"]
    C --> D["调用 main"]
    B -->|否| E["说明文件被其他模块导入"]
    E --> F["只提供函数和类,不执行业务入口"]

如果不写入口判断,别人导入你的函数时,脚本里的业务逻辑也可能被执行。

商业 Demo:订单金额计算脚本

需求:编写一个命令行脚本,输入商品单价、数量、折扣、是否会员,输出订单应付金额。要求:

  1. 单价必须大于等于 0。
  2. 数量必须大于 0。
  3. 折扣范围是 0 到 1。
  4. 会员额外减 5%。
  5. 输入非法时提示用户重新输入。

完整 Demo:

python
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()

执行流程:

mermaid
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 中的作用
变量保存单价、数量、折扣
类型转换把输入字符串转成 Decimalintbool
条件判断判断会员、判断非法参数
循环输入错误时重复提示
函数拆分读取、转换、计算逻辑
异常处理转换失败和业务校验失败
main 入口让脚本可运行也可导入测试

常见错误和排查

错误示例原因解决
IndentationError缩进不一致Python 用缩进表示代码块统一 4 空格
NameError使用未定义变量当前作用域找不到名字检查变量是否先赋值
TypeError"1" + 2类型不兼容先做类型转换
ValueErrorint("abc")值格式不合法捕获异常并提示
IndexErrorusers[10]下标越界访问前检查长度
KeyErroruser["email"]字典没有这个 keyget() 或先判断
死循环while True 无退出条件永远成立加退出条件、最大次数

排查思路:

mermaid
flowchart TD
    A["程序报错"] --> B["先看错误类型"]
    B --> C["再看文件名和行号"]
    C --> D["看报错行使用了哪些变量"]
    D --> E["打印 type 和 value"]
    E --> F["确认输入、类型转换、分支是否符合预期"]

面试标准回答

Python 变量的本质是什么?

标准回答:Python 变量本质上是名字对对象的引用。赋值不是把值复制进盒子,而是让变量名指向某个对象。多个变量可以指向同一个可变对象,所以修改列表、字典这类可变对象时,其他引用也能看到变化。

Python 为什么用缩进?

标准回答:Python 用缩进表示代码块,缩进是语法的一部分,不只是格式。这样代码结构更统一,但要求同一代码块缩进一致,不能混用 Tab 和空格。

is== 有什么区别?

标准回答:== 比较两个对象的值是否相等,is 比较两个变量是否引用同一个对象。判断是否为 None 时应该用 is None,普通值比较通常用 ==

python
a = [1, 2]
b = [1, 2]
print(a == b)  # True
print(a is b)  # False

if 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. 写一个脚本,输入分数后输出优秀、及格、不及格。
  2. 遍历 1 到 100,打印所有偶数。
  3. 定义一个用户字典,安全读取不存在的 email 字段。
  4. 写一个函数计算列表平均值,空列表返回 0。
  5. 把脚本逻辑放入 main(),并使用入口判断。
  6. 扩展订单金额 Demo:增加满 100 减 10 的优惠。
  7. 故意输入非法单价,观察错误如何被处理。

关联知识点

小结

Python 基础语法的重点不是写得短,而是写得清楚、可运行、可排查。变量是对象引用,缩进决定代码块,外部输入必须校验,循环必须有退出条件,金额计算要注意精度,脚本要有 main 入口。真正掌握这些基础后,再学习数据结构、函数模块、文件、Web、AI 才会顺畅。