Skip to main content
☘️ Septvean's Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

入门教程

下面是一份面向零基础、基于 Python 3.12 的入门教程。建议按照章节顺序学习,并亲手运行每一段代码。

一、认识 Python

Python 是一种简洁、易读、功能强大的编程语言,常用于:

  • 自动化办公
  • 数据分析
  • 网络爬虫
  • Web 开发
  • 人工智能
  • 科学计算
  • 运维脚本
  • 股票数据处理

Python 程序通常按照从上到下的顺序执行。

第一个 Python 程序:

print("Hello, Python!")

运行结果:

Hello, Python!

二、安装 Python 3.12

1. 检查 Python 版本

在终端或命令提示符中运行:

python --version

部分系统需要使用:

python3 --version

输出类似:

Python 3.12.10

2. 进入 Python 交互环境

python3

进入后可以直接执行:

>>> 1 + 2
3

退出交互环境:

exit()

3. 执行 Python 文件

创建文件:

hello.py

写入:

print("你好,Python")

运行:

python3 hello.py

三、代码基本规则

1. 注释

单行注释使用 #:

# 这是一个注释
print("Hello")

多行说明通常使用多个 #:

# 计算商品总价
# 商品单价为 10 元
# 购买数量为 5 个
total = 10 * 5

也可以使用三引号编写文档字符串:

"""
这是一个多行说明。
通常用于函数、类和模块的文档。
"""

2. 缩进

Python 使用缩进表示代码层级,一般使用四个空格:

age = 20
if age >= 18:
    print("成年人")

下面的代码会报错:

if age >= 18:
print("成年人")

3. 大小写敏感

以下变量是三个不同的变量:

name = "Tom"
Name = "Jerry"
NAME = "Alice"

四、变量

变量用于保存数据。

name = "张三"
age = 25
height = 1.75

其中:

  • name 保存字符串
  • age 保存整数
  • height 保存小数

1. 变量命名规则

变量名可以包含:

  • 字母
  • 数字
  • 下划线

但是不能以数字开头。

正确示例:

user_name = "Martin"
age2 = 30
stock_code = "600519"

错误示例:

2age = 30
user-name = "Martin"

推荐使用小写字母和下划线:

total_price = 100
user_age = 25

2. 同时给多个变量赋值

name, age, city = "张三", 25, "成都"

也可以给多个变量赋同一个值:

a = b = c = 0

3. 查看变量类型

name = "张三"
age = 25
print(type(name))
print(type(age))

结果:

<class 'str'>
<class 'int'>

五、基本数据类型

Python 常见数据类型包括:

类型 名称 示例
int 整数 10
float 浮点数 3.14
str 字符串 “Python”
bool 布尔值 True
NoneType 空值 None

Python 是动态类型语言,不用声明类型,但是可以添加类型注解,方便阅读代码。

1. 整数 int

age: int = 30
count: int = -10
number: int = 0

Python 整数没有固定长度限制:

large_number: int = 123456789012345678901234567890
print(large_number)

2. 浮点数 float

price: float = 12.5
temperature: float = -3.8

浮点数计算可能出现精度误差:

print(0.1 + 0.2)

结果可能是:

0.30000000000000004

财务计算需要精确小数时,可以使用 Decimal:

from decimal import Decimal
result = Decimal("0.1") + Decimal("0.2")
print(result)

结果:

0.3

3. 字符串 str

字符串可以使用单引号或双引号:

name: str = "Python"
city: str = '成都'

多行字符串:

text: str = """
第一行
第二行
第三行
"""

4. 布尔值 bool

布尔值只有两个:

True
False

例如:

is_open: bool = True
is_deleted: bool = False

注意首字母必须大写。

5. 空值 None

result: None = None

None 表示当前没有值:

if result is None:
    print("暂时没有结果")

六、类型转换

1. 转换为整数

age: int = int("25")
print(age)

字符串必须是合法整数:

int("25")      # 正确
int("25.5")    # 报错

浮点数转换为整数时,小数部分会被直接删除:

number: int = int(3.99)
print(number)

结果:

3

2. 转换为浮点数

price: float = float("19.9")

3. 转换为字符串

age: int = 25
text: str = str(age)

4. 转换为布尔值

以下值转换为布尔值时为 False:

False
None
0
0.0
""
[]
{}
set()

其他大多数值为 True:

print(bool(1))
print(bool("Python"))
print(bool([1, 2]))

七、输入和输出

1. 输出 print

print("Hello")
print(100)
print(3.14)

一次输出多个值:

name = "张三"
age = 25
print(name, age)

指定分隔符:

print("2026", "07", "10", sep="-")

结果:

2026-07-10

指定结尾:

print("Hello", end=" ")
print("Python")

结果:

Hello Python

2. 输入 input

name = input("请输入你的名字:")
print("你好,", name)

input() 返回的数据永远是字符串。

例如:

age = input("请输入年龄:")
print(type(age))

即使输入 25,类型仍然是 str。

需要转换:

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

八、字符串操作

1. 字符串拼接

first_name = "张"
last_name = "三"
full_name = first_name + last_name
print(full_name)

字符串不能直接和整数拼接:

age = 25
# 错误
print("年龄:" + age)

正确写法:

print("年龄:" + str(age))

更推荐使用格式化字符串。

2. f-string

格式化字符串,使用 f 前缀。

name = "张三"
age = 25
print(f"姓名:{name},年龄:{age}")

表达式也可以写在大括号中:

price = 20
count = 3
print(f"总价:{price * count} 元")

控制小数位数:

price = 12.34567
print(f"{price:.2f}")

结果:

12.35

3. 字符串索引

text = "Python"
print(text[0])
print(text[1])
print(text[-1])

结果:

P
y
n

索引从 0 开始。

4. 字符串切片

基本格式:

字符串[开始位置:结束位置:步长]

示例:

text = "Python"
print(text[0:3])
print(text[:3])
print(text[3:])
print(text[::-1])

结果:

Pyt
Pyt
hon
nohtyP

切片不包含结束位置。

5. 常用字符串方法

text = "  Hello Python  "
print(text.strip()) # 去掉首尾空格
print(text.lower()) # 转为小写
print(text.upper()) # 转为大写
print(text.replace("Python", "World")) # 替换

判断开头和结尾:

code = "600519"
print(code.startswith("60")) # 判断开头
print(code.endswith("19")) # 判断结尾

查找内容:

text = "Python is easy"
print(text.find("easy")) # 查找
print("Python" in text) # 判断包含

分割字符串:

codes = "600519,000001,300750"
code_list = codes.split(",") # 分割
print(code_list) # ['600519', '000001', '300750']

连接字符串:

words = ["Python", "Java", "Go"]
result = "、".join(words) # 连接
print(result) # Python、Java、Go

九、运算符

1. 算术运算符

+  -  *  /  //  %  **
a = 10
b = 3
print(a + b)   # 加法
print(a - b)   # 减法
print(a * b)   # 乘法
print(a / b)   # 除法
print(a // b)  # 整除
print(a % b)   # 取余
print(a ** b)  # 幂运算

2. 比较运算符

==  !=  >  <  >=  <=
a = 10
b = 20
print(a == b)
print(a != b)
print(a > b)
print(a < b)
print(a >= b)
print(a <= b)

比较结果是布尔值。

3. 逻辑运算符

and  or  not

and

所有条件都成立,结果才成立:

age = 25
has_ticket = True
print(age >= 18 and has_ticket)

or

至少一个条件成立即可:

day = "星期六"
print(day == "星期六" or day == "星期日")

not

对结果取反:

is_closed = False
print(not is_closed)

4. 成员运算符

in  not in  is  is not
stocks = ["贵州茅台", "宁德时代", "比亚迪"]
print("贵州茅台" in stocks)
print("工商银行" not in stocks)
print("贵州茅台" is "宁德时代")
print("贵州茅台" is not "比亚迪")

5. 赋值运算符

number = 10
number += 5
number -= 2
number *= 3
number /= 2

十、条件判断

1. if

age = 20
if age >= 18:
    print("你已经成年")

2. if…else

age = 16
if age >= 18:
    print("成年人")
else:
    print("未成年人")

3. if…elif…else

score = 85
if score >= 90:
    print("优秀")
elif score >= 80:
    print("良好")
elif score >= 60:
    print("及格")
else:
    print("不及格")

条件判断从上到下执行,满足一个条件后,后面的分支不再执行。

4. 嵌套判断

age = 20
has_ticket = True
if age >= 18:
    if has_ticket:
        print("允许进入")
    else:
        print("请先购票")
else:
    print("年龄不符合要求")

5. 三元表达式

普通写法:

age = 20
if age >= 18:
    result = "成年"
else:
    result = "未成年"

简化写法:

result = "成年" if age >= 18 else "未成年"

6. match 语句

Python 3.10 及以上支持结构模式匹配:

status = 404
match status:
    case 200:
        print("请求成功")
    case 404:
        print("资源不存在")
    case 500:
        print("服务器错误")
    case _:
        print("未知状态")

_ 表示其他情况。


十一、循环

1. for 循环

遍历列表:

names = ["张三", "李四", "王五"]
for name in names:
    print(name)

遍历字符串:

for char in "Python":
    print(char)

2. range

生成数字序列:

for number in range(5):
    print(number)

结果:

0
1
2
3
4

指定开始位置:

for number in range(1, 6):
    print(number)

指定步长:

for number in range(0, 10, 2):
    print(number)

结果:

0
2
4
6
8

3. while 循环

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

注意修改循环条件,否则可能出现死循环。

4. break

立即结束循环:

for number in range(1, 11):
    if number == 5:
        break
    print(number)

结果:

1
2
3
4

5. continue

跳过当前循环:

for number in range(1, 6):
    if number == 3:
        continue
    print(number)

结果:

1
2
4
5

6. pass

占位符,不执行任何操作:

for number in range(1, 6):
    if number == 3:
        pass

7. enumerate

同时获取索引和值:

names = ["张三", "李四", "王五"]
for index, name in enumerate(names):
    print(index, name)

从 1 开始编号:

for index, name in enumerate(names, start=1):
    print(index, name)

8. zip

同时遍历多个序列:

names = ["张三", "李四", "王五"]
scores = [80, 90, 75]
for name, score in zip(names, scores):
    print(name, score)

十二、列表 list

列表用于保存一组有顺序、可修改的数据。

stocks = ["贵州茅台", "比亚迪", "宁德时代"]

1. 访问列表元素

print(stocks[0])
print(stocks[-1])

2. 修改元素

stocks[0] = "五粮液"

3. 添加元素

末尾添加:

stocks.append("中国平安")

指定位置插入:

stocks.insert(1, "招商银行")

一次添加多个元素:

stocks.extend(["中际旭创", "工业富联"])

4. 删除元素

按照值删除:

stocks.remove("比亚迪")

按照索引删除并返回:

deleted_stock = stocks.pop(0)

删除指定位置:

del stocks[1]

清空列表:

stocks.clear()

5. 列表长度

print(len(stocks))

6. 排序

numbers = [5, 2, 9, 1]
numbers.sort()
print(numbers)

降序:

numbers.sort(reverse=True)

不修改原列表:

numbers = [5, 2, 9, 1]
new_numbers = sorted(numbers)

7. 统计和查找

numbers = [55, 66, 66, 77, 88]
print(numbers.count(66)) # 2
print(numbers.index(77)) # 3
print(max(numbers)) # 88
print(min(numbers)) # 55
print(sum(numbers)) # 352

8. 列表切片

numbers = [10, 20, 30, 40, 50]
print(numbers[1:4]) # [20, 30, 40]
print(numbers[:3]) # [10, 20, 30]
print(numbers[::-1]) # [50, 40, 30, 20, 10]

9. 列表推导式

普通写法:

squares = []
for number in range(1, 6):
    squares.append(number ** 2)

列表推导式:

squares = [number ** 2 for number in range(1, 6)]

带条件:

even_numbers = [
    number
    for number in range(1, 11)
    if number % 2 == 0
]

十三、元组 tuple

元组和列表相似,但创建后不能修改。

  • 不可变
point = (10, 20)

访问元素:

print(point[0])

元组不能修改:

point[0] = 100

上面的代码会报错。

1. 单元素元组

必须保留逗号:

value = (10,)

下面不是元组:

value = (10)

2. 元组解包

name, age, city = ("张三", 25, "成都")
print(name)
print(age)
print(city)

交换变量:

a = 10
b = 20
a, b = b, a

十四、字典 dict

字典使用键值对保存数据。

stock = {
    "code": "600519",
    "name": "贵州茅台",
    "price": 1500.0,
}

stock.keys()
stock.values()

1. 获取字典值

print(stock["name"])

使用不存在的键会报错:

print(stock["industry"])

更安全的方法:

print(stock.get("industry"))
print(stock.get("industry", "未知行业"))

2. 添加和修改

stock["industry"] = "白酒"
stock["price"] = 1520.0

3. 删除键值对

stock.pop("price")

或者:

del stock["industry"]

4. 遍历字典

遍历键:

  • 使用 for 循环,默认迭代键。
for key in stock:
    print(key)

遍历值:

for value in stock.values():
    print(value)

同时遍历键和值:

for key, value in stock.items():
    print(key, value)

5. 判断键是否存在

if "code" in stock:
    print(stock["code"])

6. 字典推导式

squares = {
    number: number ** 2
    for number in range(1, 6)
}

结果:

{
    1: 1,
    2: 4,
    3: 9,
    4: 16,
    5: 25,
}

十五、集合 set

集合是一组无序、不重复的数据。

  • 去重 + 集合运算
numbers = {1, 2, 3, 3, 4}
print(numbers)

结果中重复的 3 会被自动删除。

1. 创建空集合

numbers = set()

注意:

value = {}

创建的是空字典,不是空集合。

2. 添加和删除

numbers.add(5)
numbers.remove(2)
numbers.discard(10)

remove() 删除不存在的元素会报错。

discard() 删除不存在的元素不会报错。

3. 集合运算

a = {1, 2, 3}
b = {3, 4, 5}
print(a | b)  # 并集
print(a & b)  # 交集
print(a - b)  # 差集
print(a ^ b)  # 对称差集

集合常用于数据去重:

codes = ["600519", "000001", "600519"]
unique_codes = list(set(codes))

十六、函数

函数用于封装可重复执行的代码。

1. 定义函数

def greet():
    print("你好")

调用函数:

greet()

2. 函数参数

def greet(name):
    print(f"你好,{name}")

调用:

greet("张三")

3. 返回值

def add(a, b):
    return a + b

调用:

result = add(10, 20)
print(result)

return 会结束函数执行。

4. 默认参数

def greet(name, message="你好"): # message 有默认参数
    print(f"{message}{name}")

调用:

greet("张三")
greet("李四", "早上好")

5. 关键字参数

def create_user(name, age, city):
    print(name, age, city)

调用时指定参数名:

create_user(
    city="成都",
    name="张三",
    age=25,
)

6. 可变参数

经典示例:

def foo(*args, **kwargs):
    pass

接收任意数量的位置参数:

def total(*numbers):
    return sum(numbers)

调用:

print(total(1, 2, 3, 4))

numbers 在函数内部是元组。

接收任意数量的关键字参数:

def show_user(**user):
    print(user)

调用:

show_user(
    name="张三",
    age=25,
    city="成都",
)

user 在函数内部是字典。

7. 类型提示

Python 3.12 支持类型提示:

def add(a: int, b: int) -> int:
    return a + b

字符串参数和返回值:

def format_code(code: str) -> str:
    return code.strip()

类型提示不会自动限制类型,但可以提高代码可读性,并帮助编辑器发现问题。

8. 文档字符串

def add(a: int, b: int) -> int:
    """
    计算两个整数之和。
    参数:
        a: 第一个整数
        b: 第二个整数
    返回:
        两个整数的和
    """
    return a + b

查看文档:

help(add)

9. 作用域(LEGB)

  • Local 局部
  • Enclosing 闭包
  • Global 全局
  • Built-in 内置

函数内部定义的变量通常只能在函数内部使用:

def test():
    message = "Hello"
    print(message)

下面会报错:

print(message)

全局变量:

message = "Hello"
def show():
    print(message)

不建议在函数中频繁修改全局变量。


十七、Lambda 表达式

Lambda 用于编写简单的匿名函数。

普通函数:

def square(number):
    return number ** 2

Lambda 写法:

square = lambda number: number ** 2

使用:

print(square(5))

常用于排序:

stocks = [
    {"name": "A公司", "price": 20},
    {"name": "B公司", "price": 10},
    {"name": "C公司", "price": 30},
]
stocks.sort(key=lambda stock: stock["price"])
print(stocks)

复杂逻辑不建议使用 Lambda。


十八、异常处理

程序运行时可能发生错误,例如:

  • 输入格式错误
  • 文件不存在
  • 除数为零
  • 字典键不存在

1. try…except

try:
    number = int(input("请输入整数:"))
    print(number)
except ValueError:
    print("输入内容不是合法整数")

2. 捕获多个异常

try:
    a = int(input("请输入第一个数字:"))
    b = int(input("请输入第二个数字:"))
    print(a / b)
except ValueError:
    print("请输入合法数字")
except ZeroDivisionError:
    print("除数不能为零")

3. else

没有发生异常时执行:

try:
    number = int(input("请输入整数:"))
except ValueError:
    print("输入错误")
else:
    print(f"输入成功:{number}")

4. finally

无论是否发生异常都会执行:

try:
    print("执行程序")
finally:
    print("程序结束")

5. 主动抛出异常

def set_age(age: int) -> None:
    if age < 0:
        raise ValueError("年龄不能小于零")
    print(f"年龄:{age}")

十九、文件操作

1. 写入文本文件

with open(
    "example.txt",
    "w",
    encoding="utf-8",
) as file:
    file.write("第一行\n")
    file.write("第二行\n")

w 表示写入模式,会覆盖原文件。

2. 追加内容

with open(
    "example.txt",
    "a",
    encoding="utf-8",
) as file:
    file.write("第三行\n")

a 表示追加模式。

3. 读取全部内容

with open(
    "example.txt",
    "r",
    encoding="utf-8",
) as file:
    content = file.read()
print(content)

4. 按行读取

with open(
    "example.txt",
    "r",
    encoding="utf-8",
) as file:
    for line in file:
        print(line.strip())

5. 使用 pathlib

现代 Python 更推荐使用 pathlib:

from pathlib import Path
file_path = Path("example.txt")
file_path.write_text(
    "Hello Python",
    encoding="utf-8",
)
content = file_path.read_text(
    encoding="utf-8",
)
print(content)

判断文件是否存在:

if file_path.exists():
    print("文件存在")

创建目录:

folder = Path("data")
folder.mkdir(
    parents=True,
    exist_ok=True,
)

二十、JSON 数据

JSON 是程序之间交换数据的常见格式。

1. 字典转换为 JSON 字符串

import json
stock = {
    "code": "600519",
    "name": "贵州茅台",
    "price": 1500.0,
}
json_text = json.dumps(
    stock,
    ensure_ascii=False,
    indent=2,
)
print(json_text)

2. JSON 字符串转换为字典

import json
json_text = """
{
  "code": "600519",
  "name": "贵州茅台"
}
"""
stock = json.loads(json_text)
print(stock["name"])

3. 写入 JSON 文件

import json
data = {
    "name": "张三",
    "age": 25,
}
with open(
    "user.json",
    "w",
    encoding="utf-8",
) as file:
    json.dump(
        data,
        file,
        ensure_ascii=False,
        indent=2,
    )

4. 读取 JSON 文件

import json
with open(
    "user.json",
    "r",
    encoding="utf-8",
) as file:
    data = json.load(file)
print(data)

二十一、模块和包

一个 Python 文件就是一个模块。

假设存在文件:

calculator.py

内容:

def add(a: int, b: int) -> int:
    return a + b
def subtract(a: int, b: int) -> int:
    return a - b

在另一个文件中导入:

import calculator
result = calculator.add(10, 20)
print(result)

只导入某个函数:

from calculator import add
print(add(10, 20))

设置别名:

import calculator as calc
print(calc.add(10, 20))

1. 常用标准库

math

import math
print(math.sqrt(16)) # 平方根, 4.0
print(math.ceil(3.2)) # 向上取整, 3
print(math.floor(3.8)) # 向下取整, 4

random

import random
print(random.randint(1, 10))

随机选择:

names = ["张三", "李四", "王五"]
print(random.choice(names))

datetime

from datetime import datetime
now = datetime.now()
print(now)
print(now.strftime("%Y-%m-%d %H:%M:%S"))

statistics

import statistics
numbers = [10, 20, 30, 40]
print(statistics.mean(numbers)) # 平均值
print(statistics.median(numbers)) # 中位数

二十二、安装第三方库

Python 自带的库叫标准库。

其他开发者编写的库叫第三方库,需要使用 pip 安装。

查看 pip 版本:

python3 -m pip --version

安装库:

python3 -m pip install requests

卸载库:

python3 -m pip uninstall requests

查看已经安装的库:

python3 -m pip list

二十三、虚拟环境

虚拟环境用于隔离不同项目的依赖。

1. 创建虚拟环境

python3 -m venv .venv

2. 激活虚拟环境

macOS 或 Linux:

source .venv/bin/activate

Windows PowerShell:

.venv\Scripts\Activate.ps1

Windows CMD:

.venv\Scripts\activate.bat

激活后,终端通常会显示:

(.venv)

3. 退出虚拟环境

deactivate

4. 导出依赖

python3 -m pip freeze > requirements.txt

安装项目依赖:

python3 -m pip install -r requirements.txt

二十四、面向对象基础

面向对象用于把数据和行为组织在一起。

1. 定义类

class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age
    def introduce(self) -> None:
        print(f"我叫{self.name},今年{self.age}岁")

创建对象:

person = Person("张三", 25)
person.introduce()

2. self

self 表示当前对象本身。

self.name

表示当前对象的 name 属性。

3. 类属性

class Person:
    species = "人类"
    def __init__(self, name: str):
        self.name = name

访问类属性:

print(Person.species)

4. 继承

# 父类
class Animal:
    def speak(self) -> None:
        print("动物发出声音")

# 子类 (继承 Animal)
class Dog(Animal):
    def speak(self) -> None:
        print("汪汪")

使用:

dog = Dog()
dog.speak()

5. 数据类 dataclass

Python 3.12 中,可以使用 dataclass 简化数据类:

from dataclasses import dataclass
@dataclass
class Stock:
    code: str
    name: str
    price: float

创建对象:

stock = Stock(
    code="600519",
    name="贵州茅台",
    price=1500.0,
)
print(stock)

二十五、迭代器和生成器

1. 生成器函数

生成器使用 yield 返回数据:

def number_generator():
    yield 1
    yield 2
    yield 3

使用:

for number in number_generator():
    print(number)

生成器不会一次性把所有数据放入内存,适合处理大量数据。

2. 生成器表达式

numbers = (
    number ** 2
    for number in range(1, 6)
)
for number in numbers:
    print(number)

列表推导式使用方括号:

[number ** 2 for number in range(1, 6)]

生成器表达式使用圆括号:

(number ** 2 for number in range(1, 6))

二十六、常用内置函数

len

print(len("Python"))
print(len([1, 2, 3]))

sum

print(sum([10, 20, 30]))

max 和 min

numbers = [10, 5, 20]
print(max(numbers))
print(min(numbers))

sorted

numbers = [3, 1, 2]
new_numbers = sorted(numbers)

round

print(round(3.14159, 2))

abs

print(abs(-10))

all

所有元素都为真时返回 True:

print(all([True, True, True]))

any

至少一个元素为真时返回 True:

print(any([False, False, True]))

map

numbers = [1, 2, 3]
result = map(
    lambda number: number ** 2,
    numbers,
)
print(list(result))

在简单场景下,通常更推荐列表推导式:

result = [
    number ** 2
    for number in numbers
]

filter

numbers = [1, 2, 3, 4, 5]
result = filter(
    lambda number: number % 2 == 0,
    numbers,
)
print(list(result))

也可以使用列表推导式:

result = [
    number
    for number in numbers
    if number % 2 == 0
]

二十七、类型提示进阶

Python 3.12 可以直接使用内置类型编写类型提示:

def get_names() -> list[str]:
    return ["张三", "李四"]

字典类型:

def get_stock() -> dict[str, str]:
    return {
        "code": "600519",
        "name": "贵州茅台",
    }

可选值:

def find_name(user_id: int) -> str | None:
    if user_id == 1:
        return "张三"
    return None

多个可能的类型:

def format_value(value: int | float | str) -> str:
    return str(value)

类型别名:

type StockCode = str
def normalize_code(code: StockCode) -> StockCode:
    return code.strip()

type 类型别名语法是 Python 3.12 的新语法之一。

泛型函数:

def first[T](items: list[T]) -> T | None:
    if not items:
        return None
    return items[0]

这也是 Python 3.12 支持的新泛型语法。


二十八、main 入口

Python 文件可以直接运行,也可以被其他文件导入。

def main() -> None:
    print("程序开始运行")

if __name__ == "__main__":
    main()

当文件被直接运行时:

__name__ == "__main__"

条件成立。

当文件被其他模块导入时,main() 不会自动执行。

推荐将程序入口写成:

def main() -> None:
    pass

if __name__ == "__main__":
    main()

二十九、代码风格

1. 使用四个空格缩进

if age >= 18:
    print("成年人")

2. 变量名使用小写和下划线

user_name = "张三"
stock_code = "600519"

3. 类名使用大驼峰

class StockAnalyzer:
    pass

4. 常量使用大写

MAX_RETRY_COUNT = 3
DEFAULT_TIMEOUT = 10

5. 函数只负责一项任务

不推荐:

def process_everything():
    # 读取文件
    # 清洗数据
    # 发送请求
    # 保存数据库
    pass

推荐拆分:

def read_data():
    pass
def clean_data():
    pass
def save_data():
    pass

6. 避免过度嵌套

不推荐:

if condition1:
    if condition2:
        if condition3:
            print("执行")

可以使用提前返回:

def process(
    condition1: bool,
    condition2: bool,
    condition3: bool,
) -> None:
    if not condition1:
        return
    if not condition2:
        return
    if not condition3:
        return
    print("执行")

三十、综合练习一:判断股票代码

需求:

  • 参数必须是字符串
  • 长度必须是 6 位
  • 以 00 开头,转换为 33-00
  • 以 60 开头,转换为 17-60
  • 其他代码返回原值
def convert_code(code: str) -> str:
    """
    根据股票代码开头转换代码格式。
    """
    if not isinstance(code, str):
        raise TypeError("code 必须是字符串")
    if len(code) != 6:
        raise ValueError("code 长度必须为 6 位")
    if not code.isdigit():
        raise ValueError("code 必须全部由数字组成")
    if code.startswith("00"):
        return f"33-{code[:2]}"
    if code.startswith("60"):
        return f"17-{code[:2]}"
    return code

def main() -> None:
    codes = [
        "000001",
        "600519",
        "300750",
    ]
    for code in codes:
        result = convert_code(code)
        print(code, result)

if __name__ == "__main__":
    main()

运行结果:

000001 33-00
600519 17-60
300750 300750

三十一、综合练习二:通讯录程序

contacts: dict[str, str] = {}

def add_contact(name: str, phone: str) -> None:
    contacts[name] = phone
    print("联系人添加成功")

def find_contact(name: str) -> None:
    phone = contacts.get(name)
    if phone is None:
        print("没有找到联系人")
        return
    print(f"{name}{phone}")

def show_contacts() -> None:
    if not contacts:
        print("通讯录为空")
        return
    for name, phone in contacts.items():
        print(f"{name}{phone}")

def main() -> None:
    while True:
        print("\n1. 添加联系人")
        print("2. 查找联系人")
        print("3. 显示全部联系人")
        print("4. 退出")
        choice = input("请选择:").strip()
        match choice:
            case "1":
                name = input("请输入姓名:").strip()
                phone = input("请输入电话:").strip()
                add_contact(name, phone)
            case "2":
                name = input("请输入姓名:").strip()
                find_contact(name)
            case "3":
                show_contacts()
            case "4":
                print("程序结束")
                break
            case _:
                print("无效选项")

if __name__ == "__main__":
    main()

三十二、综合练习三:统计文本中的词频

def count_words(text: str) -> dict[str, int]:
    words = text.lower().split()
    result: dict[str, int] = {}
    for word in words:
        result[word] = result.get(word, 0) + 1
    return result

def main() -> None:
    text = "Python is easy Python is powerful"
    word_counts = count_words(text)
    for word, count in word_counts.items():
        print(word, count)

if __name__ == "__main__":
    main()

运行结果:

python 2
is 2
easy 1
powerful 1

三十三、综合练习四:处理 JSON 股票数据

import json
from pathlib import Path

def load_stocks(file_path: Path) -> list[dict[str, object]]:
    if not file_path.exists():
        raise FileNotFoundError(f"文件不存在:{file_path}")
    text = file_path.read_text(encoding="utf-8")
    data = json.loads(text)
    if not isinstance(data, list):
        raise ValueError("JSON 根节点必须是列表")
    return data

def show_stocks(stocks: list[dict[str, object]]) -> None:
    for stock in stocks:
        code = stock.get("code", "")
        name = stock.get("name", "")
        price = stock.get("price", 0)
        print(f"{code} {name} {price}")

def main() -> None:
    file_path = Path("stocks.json")
    try:
        stocks = load_stocks(file_path)
    except FileNotFoundError as error:
        print(error)
    except json.JSONDecodeError:
        print("JSON 文件格式错误")
    except ValueError as error:
        print(error)
    else:
        show_stocks(stocks)

if __name__ == "__main__":
    main()

stocks.json 示例:

[
  {
    "code": "600519",
    "name": "贵州茅台",
    "price": 1500.0
  },
  {
    "code": "000001",
    "name": "平安银行",
    "price": 11.5
  }
]

三十四、常见错误

1. SyntaxError

语法错误:

if age >= 18
    print("成年")

缺少冒号。

正确:

if age >= 18:
    print("成年")

2. NameError

使用了不存在的变量:

print(user_name)

需要先定义:

user_name = "张三"
print(user_name)

3. TypeError

类型不匹配:

"年龄:" + 25

正确:

"年龄:" + str(25)

或者:

f"年龄:{25}"

4. ValueError

值的格式不正确:

int("abc")

5. IndexError

列表索引超出范围:

numbers = [1, 2, 3]
print(numbers[10])

6. KeyError

字典键不存在:

user = {"name": "张三"}
print(user["age"])

可以使用:

print(user.get("age"))

7. AttributeError

对象没有对应方法或属性:

number = 100
number.append(1)

整数没有 append() 方法。


三十五、建议的学习顺序

第一阶段:基础语法

  1. 变量
  2. 数据类型
  3. 输入输出
  4. 运算符
  5. 条件判断
  6. 循环

第二阶段:数据结构

  1. 字符串
  2. 列表
  3. 元组
  4. 字典
  5. 集合

第三阶段:程序组织

  1. 函数
  2. 异常处理
  3. 文件操作
  4. JSON
  5. 模块和包

第四阶段:进阶基础

  1. 面向对象
  2. 类型提示
  3. 生成器
  4. 虚拟环境
  5. 第三方库

第五阶段:项目实践

可以选择一个方向:

  • Excel 自动化
  • 股票数据分析
  • 网络爬虫
  • 数据库操作
  • Web API
  • 文件批量处理
  • 日常办公自动化

三十六、入门练习题

练习一

输入姓名和年龄,输出:

你好,张三,你明年 26 岁。

参考思路:

name = input("请输入姓名:")
age = int(input("请输入年龄:"))
print(f"你好,{name},你明年 {age + 1} 岁。")

练习二

输入一个整数,判断奇数还是偶数。

number = int(input("请输入整数:"))
if number % 2 == 0:
    print("偶数")
else:
    print("奇数")

练习三

计算 1 到 100 的总和。

total = 0
for number in range(1, 101):
    total += number
print(total)

也可以直接使用:

print(sum(range(1, 101)))

练习四

找出列表中的最大值,但不使用 max()。

numbers = [10, 35, 12, 80, 6]
largest = numbers[0]
for number in numbers[1:]:
    if number > largest:
        largest = number
print(largest)

练习五

删除列表中的重复元素,并保持原顺序。

numbers = [1, 2, 2, 3, 1, 4]
result = []
for number in numbers:
    if number not in result:
        result.append(number)
print(result)

练习六

统计字符串中每个字符出现的次数。

text = "hello"
counts = {}
for char in text:
    counts[char] = counts.get(char, 0) + 1
print(counts)

练习七

编写函数,判断股票代码是否合法。

规则:

  • 必须是字符串
  • 长度为 6 位
  • 全部由数字组成
def is_valid_stock_code(code: str) -> bool:
    return (
        isinstance(code, str)
        and len(code) == 6
        and code.isdigit()
    )

三十七、一个完整项目的基本结构

简单项目可以使用以下目录:

stock_project/
├── .venv/
├── data/
│   └── stocks.json
├── src/
│   ├── __init__.py
│   ├── loader.py
│   └── analyzer.py
├── tests/
│   └── test_analyzer.py
├── main.py
├── requirements.txt
└── README.md

main.py:

from src.loader import load_data
from src.analyzer import analyze_data

def main() -> None:
    data = load_data()
    result = analyze_data(data)
    print(result)

if __name__ == "__main__":
    main()

这种结构能够把:

  • 数据读取
  • 数据处理
  • 程序入口
  • 测试代码

分别组织起来。


三十八、入门阶段需要掌握的核心能力

学习完本教程后,应当能够:

  1. 创建和使用变量。
  2. 理解整数、浮点数、字符串和布尔值。
  3. 使用条件判断处理不同情况。
  4. 使用循环批量处理数据。
  5. 使用列表、字典和集合组织数据。
  6. 编写带参数和返回值的函数。
  7. 读取和写入文本及 JSON 文件。
  8. 使用异常处理提高程序稳定性。
  9. 创建虚拟环境并安装第三方库。
  10. 编写结构清晰的小型 Python 项目。

真正掌握 Python 的关键不是记住所有语法,而是不断完成以下过程:

明确需求
→ 拆分步骤
→ 编写代码
→ 运行测试
→ 阅读错误
→ 修改代码
→ 总结规律

编程能力主要来自持续实践,而不是单纯阅读。