欢迎光临
我们一直在努力

Python 入门教程(面向有 Java 经验的开发者)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}

Python 入门教程(面向有 Java 经验的开发者)

这不是一份“Python 知识点罗列”,而是一份可以顺着学下去的教程。

目标:让已经有 Java 经验的开发者,在最短时间内建立 Python 的开发直觉,并能开始写脚本、做小工具、看懂常见 Python 项目代码。

这份教程怎么用

建议按顺序学习,不要跳着看。

每一章都尽量遵循同一种结构:

  • 先讲这一章到底要学会什么
  • 再给最小必要知识
  • 再给 Java 对照,帮助你迁移已有经验
  • 最后给练习,帮助你真正掌握

推荐节奏:

  • 每次学 1 章
  • 先自己照着敲代码,不要只看
  • 每章末尾练习至少做 2 题
  • 卡住时回看原始完整稿:尚硅谷大模型技术之 Python(V3.0).md

学习路线总览

如果你有 Java 经验,第一轮只需要拿下这 7 件事:

  • Python 的基本语法和缩进规则
  • 常用数据类型与容器
  • 条件、循环、函数
  • 字符串、切片、推导式
  • Python 风格的面向对象
  • 模块、异常、文件操作
  • 一些最常见的 Pythonic 写法
  • 下面正式开始。


    第 1 章 先跑起来:用 Python 写第一个程序

    你要学会什么

    学完这一章,你应该能:

    • 安装并运行 Python 程序
    • 理解 Python 文件如何执行
    • 知道 Python 和 Java 在运行方式上的核心区别

    1.1 先准备环境

    建议使用 Python 3.11+。

    查看版本:

    python3 -V

    创建虚拟环境:

    python3 -m venv .venv
    source .venv/bin/activate

    安装包时尽量用:

    python -m pip install requests

    而不是直接写 pip install,因为前者更明确地绑定当前解释器。

    1.2 第一个 Python 程序

    创建 hello.py:

    print('hello python')

    运行:

    python hello.py

    1.3 先建立一个和 Java 不一样的认知

    Java 中你通常会写:

    public class Hello {
    public static void main(String[] args) {
    System.out.println("hello");
    }
    }

    Python 不需要:

    • 类包裹入口
    • main 方法
    • 类型声明
    • 分号结尾

    Python 的基本哲学是:能更直接,就不要多写样板代码。

    1.4 交互式解释器很好用

    直接输入:

    python

    然后可以立刻测试:

    2 + 3
    'hello'.upper()
    len([1, 2, 3])

    这对学习和试验非常有帮助。Java 开发者往往低估了这一点。

    1.5 本章练习

  • 创建 calc.py,打印 3 * 7 的结果。
  • 进入 Python 交互模式,试一下:10 / 3、10 // 3、10 % 3。
  • 创建虚拟环境,并确认 python -V 能正常输出版本。

  • 第 2 章 语法入门:变量、类型、缩进

    你要学会什么

    学完这一章,你应该能:

    • 定义变量
    • 理解 Python 的几种基础类型
    • 正确书写缩进和代码块
    • 理解 None 的意义
    • 做最常见的类型转换和基础运算

    2.1 变量不需要声明类型

    name = 'Alice'
    age = 18
    height = 1.72
    is_admin = False

    和 Java 最大的区别是:

    • Java:变量声明时写类型
    • Python:变量不写类型,但对象本身有类型

    print(type(name))
    print(type(age))

    2.2 最常见的基础类型

    你第一轮最需要掌握这几个:

    • int
    • float
    • bool
    • str
    • None

    示例:

    count = 10
    price = 19.9
    ok = True
    title = 'Python'
    result = None

    2.3 类型转换是日常开发高频操作

    input() 读进来的内容默认是字符串,所以类型转换非常常见:

    age = int('18')
    price = float('19.9')
    name = str(123)
    flag = bool(1)

    第一轮先记住这些最常用的:

    • int():转整数
    • float():转浮点数
    • str():转字符串
    • bool():转布尔值

    要注意:

    print(bool(0))
    print(bool(''))
    print(bool('abc'))

    2.4 先掌握最常用的运算符

    算术运算:

    print(10 + 3)
    print(10 – 3)
    print(10 * 3)
    print(10 / 3)
    print(10 // 3)
    print(10 % 3)
    print(2 ** 3)

    比较与逻辑运算:

    age = 20
    print(age >= 18)
    print(age < 60 and age >= 18)
    print(age < 18 or age > 60)
    print(not False)

    对 Java 开发者来说,主要有两个容易注意的点:

    • Python 用 and / or / not,不是 && / || / !
    • == 比较值,is 比较是否为同一个对象;入门阶段先把 is 主要用在 x is None

    2.5 None 不是“空字符串”

    value = None
    print(value)

    None 更接近 Java 的 null,但要注意:

    • 它是 Python 中一个明确存在的对象
    • 常用来表示“没有值”或“还没结果”

    比如:

    def find_user(user_id):
    return None

    2.6 缩进就是语法

    age = 20

    if age >= 18:
    print('成年人')
    print('可以注册')
    else:
    print('未成年人')

    这里没有花括号。if 下面缩进的代码就是这个代码块。

    请严格记住:

    • 统一用 4 个空格
    • 不要混用 Tab 和空格
    • 同一层级缩进必须一致

    2.7 注释只需要先会一种

    # 这是一行注释

    够用了。别一开始把精力放在注释花样上。

    2.8 Java 视角总结

    这一章你只要完成 4 个观念切换:

  • Python 不写变量类型,但对象有类型。
  • Python 用缩进表达层级,不用 {}。
  • 类型转换需要主动做,尤其是 input() 之后。
  • 逻辑运算写 and / or / not。
  • 这几个点适应了,后面会顺很多。

    2.9 本章练习

  • 定义变量 name、age、salary,分别保存你的名字、年龄、薪资。
  • 打印这 3 个变量的类型。
  • 写一个 if 判断:如果年龄大于等于 18,打印“成年人”,否则打印“未成年人”。
  • 让用户输入一个数字字符串,把它转成 int 后加 10 再输出。

  • 第 3 章 字符串与输入输出

    你要学会什么

    学完这一章,你应该能:

    • 输出信息
    • 获取用户输入
    • 用 f-string 拼接字符串
    • 知道 Python 字符串是不可变对象

    3.1 输出最常用的是 print

    print('你好')
    print(123)
    print(True)

    3.2 输入最常用的是 input

    name = input('请输入你的名字: ')
    print(name)

    要特别注意:

    input() 拿到的永远是字符串。

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

    如果要做数值计算,需要手动转换:

    age = int(input('请输入年龄: '))

    3.3 优先掌握 f-string

    name = 'Alice'
    age = 18
    print(f'我叫{name},今年{age}岁')

    这是 Python 中最常用、最推荐的字符串格式化方式。

    3.4 字符串不可变

    text = 'hello'
    # text[0] = 'H' # 会报错

    这点和 Java 的 String 很像:修改字符串,通常是得到一个新字符串。

    3.5 常见字符串方法

    text = ' hello python '
    print(text.strip())
    print(text.upper())
    print(text.lower())
    print(text.replace('python', 'java'))
    print(text.split())

    第一轮记住这些就够:

    • strip():去掉两端空白
    • upper() / lower():大小写转换
    • replace():替换
    • split():拆分

    3.6 本章练习

  • 让用户输入姓名和年龄,然后打印:你好,xxx,你今年 xx 岁。
  • 输入一个带前后空格的字符串,打印去空格后的结果。
  • 输入一个英文单词,打印它的大写形式。

  • 第 4 章 容器入门:list、tuple、dict、set

    你要学会什么

    学完这一章,你应该能:

    • 正确选择最常用的 4 类容器
    • 对容器做增删改查
    • 理解它们与 Java 容器的大致对应关系
    • 掌握容器通用操作和成员判断
    • 读懂后续 AI 代码里的 dict.items()、pop()、列表推导式

    4.1 先建立总图

    Python含义Java 里大概像什么
    list 有序、可变序列 ArrayList
    tuple 有序、不可变序列 轻量只读数据
    dict 键值映射 HashMap
    set 无序不重复集合 HashSet

    4.2 list:最常用的容器

    nums = [10, 20, 30]
    nums.append(40)
    nums.insert(1, 15)
    print(nums)
    print(nums[0])
    print(nums[–1])

    删除:

    nums.pop()
    nums.remove(15)
    print(nums)

    和 Java 比,list 用起来通常更轻、更直接。

    4.3 tuple:不可变序列

    point = (100, 200)
    print(point[0])

    典型用途:

    • 作为不可修改的数据
    • 接收多返回值
    • 解包

    x, y = point

    4.4 dict:Python 业务代码里的主力军

    user = {
    'name': 'Alice',
    'age': 18,
    }

    print(user['name'])
    print(user.get('email'))
    user['age'] = 19

    遍历:

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

    如果你以后写接口、配置、JSON 处理,dict 会出现得非常频繁。

    4.5 set:去重与集合运算

    tags = {'python', 'java', 'python'}
    print(tags)

    集合运算:

    a = {1, 2, 3}
    b = {3, 4, 5}

    print(a | b)
    print(a & b)
    print(a – b)

    4.6 容器通用操作也要熟

    很多容器都支持一些通用能力:

    nums = [10, 20, 30]
    print(len(nums))
    print(20 in nums)
    print(max(nums))
    print(min(nums))
    print(sum(nums))

    这几个函数非常高频:

    • len():长度
    • in / not in:成员判断
    • max() / min():最大最小值
    • sum():求和,通常用于纯数字序列

    字符串、列表、元组大多都能配合这些操作使用。

    4.7 dict.items()、get()、pop() 后面会非常常见

    batch = {'input_ids': [1, 2], 'labels': [1]}
    print(batch.get('labels'))
    for k, v in batch.items():
    print(k, v)
    labels = batch.pop('labels')
    print(labels)
    print(batch)

    后面 AI 课程代码里会反复看到这种写法,比如:

    • for k, v in batch.items():遍历一批输入数据
    • inputs.pop('labels'):把标签从输入字典里取出来
    • word2index.get(token, unk_index):查词表,查不到就给默认值

    你如果这里不熟,后面看训练代码会容易卡住。

    4.8 切片和序列操作值得一起掌握

    nums = [10, 20, 30, 40, 50]
    print(nums[1:4])
    print(nums[:3])
    print(nums[::–1])
    print(nums + [60, 70])
    print('py' * 3)

    这里你会顺手接触到两类常见操作:

    • 切片:sequence[start:end:step]
    • 序列拼接与重复:+ 和 *

    4.9 什么时候该用哪个容器

    一个简单判断:

    • 要顺序、可修改:list
    • 要键值对:dict
    • 要去重:set
    • 要只读小结构:tuple

    4.10 本章练习

  • 定义一个列表,保存 5 个分数,打印第 1 个和最后 1 个分数。
  • 定义一个字典,保存一个人的 name、age、city。
  • 定义两个集合,输出它们的并集和交集。
  • 用 for key, value in … 的方式遍历字典。
  • 对一个数字列表分别输出长度、最大值、最小值和元素总和。
  • 写一个小字典,使用 get() 和 pop() 各操作一次。

  • 第 5 章 流程控制:if、for、while

    你要学会什么

    学完这一章,你应该能:

    • 写条件分支
    • 使用 for 遍历容器
    • 使用 while 处理重复逻辑
    • 理解 break / continue
    • 理解 Python 中真值判断的习惯写法

    5.1 if / elif / else

    score = 85

    if score >= 90:
    print('A')
    elif score >= 80:
    print('B')
    else:
    print('C')

    5.2 Python 更常用 for

    for num in [1, 2, 3]:
    print(num)

    遍历数字范围:

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

    5.3 enumerate 很好用

    names = ['Alice', 'Bob', 'Cathy']
    for index, name in enumerate(names, start=1):
    print(index, name)

    当你既想拿到序号,又想拿到元素时,优先想到它。

    5.4 while 的典型场景

    count = 0
    while count < 3:
    print(count)
    count += 1

    如果只是遍历一个容器,通常 for 比 while 更自然。

    5.5 break 和 continue 必须会

    break:提前结束整个循环。

    for num in [1, 2, 3, 4]:
    if num == 3:
    break
    print(num)

    continue:跳过本轮,进入下一轮。

    for num in [1, 2, 3, 4]:
    if num % 2 == 0:
    continue
    print(num)

    5.6 Python 的真值判断很常见

    items = []
    if not items:
    print('空列表')

    这些值通常会被当成假:

    • None
    • 0
    • 0.0
    • ''
    • []
    • {}
    • set()

    这也是 Python 代码看起来更简洁的原因之一。

    5.7 本章练习

  • 输入一个分数,输出 A/B/C。
  • 用 for 打印 1 到 10。
  • 用 while 求 1 到 100 的和。
  • 判断一个列表是否为空,并打印提示信息。
  • 遍历 1 到 10,只打印奇数。

  • 第 6 章 函数:把逻辑组织起来

    你要学会什么

    学完这一章,你应该能:

    • 定义和调用函数
    • 使用参数和返回值
    • 理解默认参数、关键字参数、可变参数
    • 理解作用域、递归、文档字符串
    • 看懂参数解包 *args / **kwargs
    • 看懂后续 AI 代码里的 model(**inputs)、list[str]

    6.1 函数定义

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

    result = add(3, 5)
    print(result)

    6.2 默认参数

    def greet(name, msg='你好'):
    print(f'{msg},{name}')

    greet('Alice')
    greet('Bob', '欢迎')

    6.3 关键字参数

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

    create_user(name='Alice', age=18, city='Shanghai')

    这会让调用代码更清晰。

    6.4 可变参数

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

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

    def show_user(**kwargs):
    print(kwargs)

    记忆方式:

    • *args 收位置参数,得到 tuple
    • **kwargs 收关键字参数,得到 dict

    6.5 参数解包调用,后面 AI 代码会直接用到

    除了“定义函数时接收”,* 和 ** 还可以在“调用函数时解包”:

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

    nums = [3, 5]
    print(add(*nums))

    def show(name, age):
    print(name, age)

    user = {'name': 'Alice', 'age': 18}
    show(**user)

    后面 AI 课程里的 BERT 训练代码会直接出现:

    outputs = model(**inputs)

    意思就是:把 inputs 这个字典拆成 key=value 参数传给模型。

    6.6 多返回值

    def get_user():
    return 'Alice', 18

    name, age = get_user()

    本质上返回的是一个元组。

    6.7 类型注解建议尽早适应

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

    对 Java 开发者来说,这会让代码更熟悉一些,也更利于 IDE 提示。

    你后面还会看到这种写法:

    def tokenize(text) –> list[str]:
    return list(text)

    这里的 list[str] 表示“元素类型是 str 的列表”。后续 tokenizer 代码里就会出现这种注解。

    6.8 作用域和 global 要有基本概念

    count = 0

    def increase():
    global count
    count += 1

    increase()
    print(count)

    先记住这几个规则:

    • 函数内部定义的变量,默认是局部变量
    • 函数外部定义的变量,是全局变量
    • 只有确实要在函数里修改全局变量时,才使用 global

    实际开发里,global 不宜滥用。大多数时候,更推荐用参数和返回值传递数据。

    6.9 递归先会看懂,再决定多用

    def factorial(n: int) –> int:
    if n == 1:
    return 1
    return n * factorial(n – 1)

    递归的两个关键点:

    • 递归终止条件
    • 每次调用都更接近终止条件

    第一轮学习时,会看懂、能写简单例子就够了。很多业务场景里,循环依然更直接。

    6.10 文档字符串和函数说明

    def add(a: int, b: int) –> int:
    """返回两个整数之和。"""
    return a + b

    这段三引号字符串就是文档字符串。它的作用是:

    • 给别人说明函数是干什么的
    • 让 IDE、帮助系统能直接显示说明
    • 让代码更容易维护

    6.11 pass 是占位关键字

    def todo():
    pass

    当语法上需要先写一个函数体、类体,但你还没实现时,可以先用 pass 占位。后面 tokenizer 的基类方法里会见到它。

    6.12 一个重要提醒

    不要把 Python 函数写成 Java 工具类那种风格:

    • 没必要所有函数都塞进一个 Utils 类
    • 没必要为了“面向对象”而强行包类

    Python 中很多逻辑直接写函数就是最自然的。

    6.13 本章练习

  • 写一个函数,接收两个数字,返回较大值。
  • 写一个函数,接收姓名和问候语,问候语默认为“你好”。
  • 写一个函数,接收任意多个数字,返回它们的和。
  • 写一个函数,返回姓名和年龄两个值,并在外部解包接收。
  • 写一个递归函数,计算 n 的阶乘。
  • 写一个接收字典参数的函数,并用 **user 的方式调用它。

  • 第 7 章 切片、推导式、排序:开始有 Python 味道

    你要学会什么

    学完这一章,你应该能:

    • 使用切片处理序列
    • 使用列表推导式替代部分循环
    • 用 sorted(…, key=…) 处理常见排序问题
    • 看懂条件表达式和简单 lambda
    • 知道 map / filter 在 Python 里的基本位置

    7.1 切片

    nums = [10, 20, 30, 40, 50]
    print(nums[1:4])
    print(nums[:3])
    print(nums[::2])
    print(nums[::–1])

    格式:

    sequence[start:end:step]

    7.2 列表推导式

    nums = [1, 2, 3, 4]
    squares = [n * n for n in nums]
    evens = [n for n in nums if n % 2 == 0]

    它本质上是在表达:

    • 从一个序列取数据
    • 做转换
    • 或加条件过滤

    这是 Python 非常重要的表达方式。

    7.3 字典推导式和集合推导式

    name_lengths = {name: len(name) for name in ['Alice', 'Bob']}
    unique_lengths = {len(name) for name in ['Alice', 'Bob', 'Tom']}

    7.4 排序时传 key

    users = [
    {'name': 'Alice', 'age': 20},
    {'name': 'Bob', 'age': 18},
    ]

    result = sorted(users, key=lambda user: user['age'])
    print(result)

    如果你用过 Java Stream,这个感觉会有点像“更轻量的转换和排序”。

    7.5 条件表达式是 if-else 的简写

    age = 20
    label = '成年人' if age >= 18 else '未成年人'
    print(label)

    当逻辑很短、只是做二选一赋值时,这种写法很常见。

    7.6 lambda 先学会看懂

    lambda 就是匿名函数,常见于“只用一次的小函数”:

    add = lambda a, b: a + b
    print(add(2, 3))

    但更常见的场景其实是配合排序、映射、过滤:

    nums = [1, 2, 3, 4]
    print(list(map(lambda x: x * 2, nums)))
    print(list(filter(lambda x: x % 2 == 0, nums)))

    学习建议:

    • 先会看懂 lambda
    • 简单场景下更优先考虑列表推导式,因为通常更直观

    7.7 本章练习

  • 把一个列表倒序输出。
  • 用列表推导式生成 1 到 10 的平方列表。
  • 从列表中筛选所有偶数。
  • 对一组字典按 age 排序。
  • 用条件表达式判断一个数字是奇数还是偶数。

  • 第 8 章 面向对象:保留 Java 开发者真正需要的部分

    你要学会什么

    学完这一章,你应该能:

    • 定义类和实例
    • 理解 self、__init__
    • 使用继承和方法重写
    • 看懂 super() 和常见特殊方法
    • 理解 Python 的鸭子类型与 Java 接口思维的不同
    • 看懂后续 AI 代码里的 nn.Module、Dataset、Tokenizer 类设计

    8.1 定义类

    class Person:
    def __init__(self, name: str, age: int):
    self.name = name
    self.age = age

    def speak(self, msg: str) –> None:
    print(f'{self.name}: {msg}')

    使用:

    p = Person('Alice', 18)
    p.speak('你好')

    8.2 self 怎么理解

    可以把 self 理解成 Java 里的 this。

    区别在于:

    • Java 里的 this 通常不写在参数列表里
    • Python 必须显式写出来

    8.3 类属性、类方法、静态方法

    class User:
    total = 0

    def __init__(self, name: str):
    self.name = name
    User.total += 1

    @classmethod
    def count(cls) –> int:
    return cls.total

    @staticmethod
    def is_valid_name(name: str) –> bool:
    return len(name.strip()) > 0

    你只需要先记住:

    • 实例方法处理对象自身状态
    • 类方法通常处理类级别状态或工厂逻辑
    • 静态方法只是“放在类里的普通函数”

    后面 AI 课程的 tokenizer 里会大量出现 @classmethod / @staticmethod,比如 from_vocab()、tokenize()。

    8.4 继承、重写、super() 都会在 AI 代码里出现

    class Animal:
    def speak(self) –> None:
    print('…')

    class Dog(Animal):
    def __init__(self, name):
    super().__init__()
    self.name = name

    def speak(self) –> None:
    print('wang')

    在后续 AI 代码里,你会看到很多类这样写:

    • class ReviewAnalyzeModel(nn.Module)
    • class TranslationDataset(Dataset)
    • super().__init__()

    这说明它们是在继承框架提供的父类能力。

    8.5 特殊方法 __len__、__getitem__ 要认识

    class MyList:
    def __init__(self, data):
    self.data = data

    def __len__(self):
    return len(self.data)

    def __getitem__(self, index):
    return self.data[index]

    这样你就可以写:

    obj = MyList([10, 20, 30])
    print(len(obj))
    print(obj[0])

    后面的自定义数据集代码会直接用这两个方法配合 DataLoader 工作,所以这不是“只会在语法书里出现的知识点”。

    8.6 鸭子类型比“接口约束”更常见

    def make_speak(obj):
    obj.speak()

    只要传入对象能调用 speak(),这段代码就可以工作。

    这就是典型的 Python 风格:

    • 不那么强调“你是什么类型”
    • 更强调“你能不能完成这个行为”

    8.7 第一轮不必深挖的 OOP 主题

    先不用急着深挖这些:

    • 魔法方法的完整体系
    • 抽象类
    • 多重继承细节
    • 元类

    先把“类怎么写、对象怎么用、继承怎么读懂”掌握住更重要。

    8.8 本章练习

  • 写一个 Student 类,包含 name 和 score。
  • 给 Student 类加一个 show() 方法,打印学生信息。
  • 写一个 Animal 和 Dog,让 Dog 重写 speak()。
  • 写一个函数,接收任意有 speak() 方法的对象并调用它。
  • 写一个类,实现 __len__ 和 __getitem__。

  • 第 9 章 模块与包:开始像写项目一样组织代码

    你要学会什么

    学完这一章,你应该能:

    • 理解模块和包
    • 使用几种常见导入方式
    • 知道 __name__ == '__main__' 的作用
    • 理解第三方包和虚拟环境的关系
    • 先知道几个常见标准库
    • 把代码从“一个文件”整理成“小项目结构”

    9.1 一个 .py 文件通常就是一个模块

    math 是模块,你自己的 user_service.py 也是模块。

    import math
    print(math.sqrt(16))

    9.2 常见导入方式

    import math
    import math as m
    from math import sqrt

    建议:

    • 日常优先 import module
    • 或 from package import module
    • 少用 from xxx import *

    9.3 __name__ == '__main__' 是什么

    def main():
    print('程序启动')

    if __name__ == '__main__':
    main()

    它的意思是:

    • 当前文件被“直接运行”时,执行这段代码
    • 当前文件被“当作模块导入”时,不执行这段代码

    这在写可复用模块时非常常见。

    9.4 一个简单项目结构

    project/
    ├── app/
    │ ├── __init__.py
    │ ├── service.py
    │ └── utils.py
    ├── main.py
    └── requirements.txt

    __init__.py 的作用,入门阶段先理解成:告诉 Python“这个目录要作为包来使用”。

    9.5 第三方包和虚拟环境

    python -m pip install requests
    python -m pip freeze > requirements.txt
    python -m pip install -r requirements.txt

    虚拟环境的核心意义是:

    • 每个项目有自己的依赖集合
    • 避免全局环境互相污染
    • 更容易和别人同步项目环境

    9.6 常见标准库先知道名字

    第一轮不需要全背,但至少知道这些高频模块:

    • pathlib:路径处理
    • json:JSON 编解码
    • datetime:日期时间
    • collections:增强型容器
    • itertools:迭代工具
    • functools:函数式工具
    • os / sys:系统交互

    以后你写脚本、做文件处理、调接口时,很快就会碰到它们。

    9.7 Java 迁移提示

    你可以把它粗略理解为:

    • 模块接近“单个源码文件里的可复用功能”
    • 包接近“目录级组织结构”

    但 Python 的导入方式通常比 Java 轻很多。

    9.8 本章练习

  • 创建 math_utils.py,写一个加法函数。
  • 在另一个文件中导入并调用这个函数。
  • 尝试给模块起别名导入。
  • 写一个带 main() 和 if __name__ == '__main__': 的脚本。

  • 第 10 章 异常处理:让程序更稳

    你要学会什么

    学完这一章,你应该能:

    • 使用 try / except 处理异常
    • 捕获特定类型异常
    • 主动抛出异常
    • 理解异常传递
    • 在需要时定义自定义异常类

    10.1 基本写法

    try:
    num = int(input('请输入数字: '))
    print(10 / num)
    except ValueError:
    print('输入的不是整数')
    except ZeroDivisionError:
    print('除数不能为 0')
    else:
    print('执行成功')
    finally:
    print('一定会执行')

    10.2 主动抛出异常

    def register(age: int) –> None:
    if age < 0:
    raise ValueError('age 不能小于 0')

    10.3 异常会向上层传递

    def divide(a, b):
    return a / b

    def calculate():
    return divide(10, 0)

    try:
    calculate()
    except ZeroDivisionError:
    print('捕获到除零错误')

    这说明:底层函数没处理的异常,会一层层往上抛,直到被某一层捕获。

    10.4 自定义异常类什么时候用

    class AgeError(Exception):
    pass

    def register(age: int) –> None:
    if age < 0:
    raise AgeError('年龄不能为负数')

    当你希望错误语义更清晰、更贴近业务时,就可以定义自己的异常类。

    10.5 3 个很实用的建议

    • 只捕获你能处理的异常
    • 不要无脑写 except Exception:
    • 错误信息尽量能帮助定位问题

    10.6 本章练习

  • 输入一个数字并输出 100 / num,处理输入错误和除零错误。
  • 写一个函数,当年龄小于 0 时抛出异常。
  • 试着分别触发 ValueError 和 ZeroDivisionError。
  • 自定义一个异常类,用来表示“用户名不能为空”。

  • 第 11 章 文件操作:这是脚本开发的高频能力

    你要学会什么

    学完这一章,你应该能:

    • 读取文本文件
    • 写入文本文件
    • 理解为什么 with 是最佳实践
    • 掌握常见文件模式
    • 理解绝对路径和相对路径
    • 初步使用 pathlib 做路径和目录操作
    • 看懂后续 AI 代码里的 Path(__file__) 和 with torch.no_grad()

    11.1 读取文件

    with open('data.txt', 'rt', encoding='utf-8') as f:
    content = f.read()
    print(content)

    11.2 写入文件

    with open('output.txt', 'wt', encoding='utf-8') as f:
    f.write('hello\\n')

    11.3 常见文件模式先记住这些

    • rt:读文本
    • wt:写文本,会覆盖原内容
    • at:追加文本,在文件末尾继续写
    • rb / wb:读写二进制文件

    追加写入示例:

    with open('log.txt', 'at', encoding='utf-8') as f:
    f.write('new line\\n')

    11.4 绝对路径 vs 相对路径

    • 绝对路径:从磁盘根位置开始写的完整路径
    • 相对路径:相对于当前工作目录的路径

    from pathlib import Path

    print(Path('data.txt').resolve())

    入门阶段的建议是:

    • 小练习先用相对路径
    • 真正做项目时,尽量明确路径基准,避免“在不同目录运行就找不到文件”

    11.5 pathlib 和 __file__ 在项目里非常常见

    from pathlib import Path

    ROOT_DIR = Path(__file__).parent
    DATA_DIR = ROOT_DIR / 'data'

    这里有两个重点:

    • __file__:当前 Python 文件自己的路径
    • Path(… ) / 'child':pathlib 提供的路径拼接写法

    后面 AI 课程里的 config.py 基本就是这样组织项目目录的,所以你最好在这里就先熟悉。

    11.6 为什么总推荐 with

    因为它和 Java 的 try-with-resources 很像:

    • 更安全
    • 自动释放资源
    • 异常时也能正确关闭文件

    而且 with 不只用于文件。后面推理代码里你还会看到:

    with torch.no_grad():
    pass

    这里的意思是:在这个代码块里关闭梯度计算,做推理更省资源。

    11.7 路径建议优先用 pathlib

    from pathlib import Path

    path = Path('logs/app.log')
    print(path.exists())
    print(path.parent)

    11.8 目录操作也很常用

    from pathlib import Path

    base = Path('data')
    base.mkdir(exist_ok=True)

    for item in base.iterdir():
    print(item)

    入门阶段先会这几个就很够用:

    • Path.exists():判断路径是否存在
    • Path.mkdir():创建目录
    • Path.iterdir():遍历目录内容
    • Path.is_file() / Path.is_dir():判断文件或目录

    11.9 本章练习

  • 读取一个文本文件,并打印内容。
  • 把一段字符串写入另一个文件。
  • 使用 Path 判断某个文件是否存在。
  • 创建一个目录,并遍历这个目录下的内容。
  • 用 Path(__file__) 的思路,写一个脚本打印当前文件所在目录。

  • 第 12 章 一些现在就该养成的 Python 习惯

    12.1 能直接遍历元素,就不要手搓下标

    不推荐:

    names = ['Alice', 'Bob']
    for i in range(len(names)):
    print(names[i])

    更推荐:

    for name in names:
    print(name)

    如果确实要索引,用 enumerate()。

    12.2 能写推导式时,不要总写冗长循环

    不推荐:

    result = []
    for n in [1, 2, 3, 4]:
    result.append(n * n)

    更推荐:

    result = [n * n for n in [1, 2, 3, 4]]

    12.3 能写函数,就不要急着写工具类

    很多 Java 开发者的惯性是:

    • 先建类
    • 再放静态方法

    但 Python 中很多场景直接写模块级函数更自然。

    12.4 优先写清晰,而不是写炫技代码

    短不是目的,清楚才是目的。

    12.5 可变对象、浅拷贝、深拷贝值得尽早知道

    import copy

    nums1 = [[1, 2], [3, 4]]
    nums2 = copy.copy(nums1)
    nums3 = copy.deepcopy(nums1)

    可以先这样理解:

    • 直接赋值:只是多个变量指向同一个对象
    • 浅拷贝:只复制最外层,里面嵌套的对象可能还是共用的
    • 深拷贝:连里面嵌套的对象也一起复制

    这在处理嵌套列表、字典时很容易踩坑,所以提前知道很有价值。

    12.6 第一轮别急着钻高级特性

    这些知识点不是不重要,而是更适合放在“已经会写普通业务代码之后”再系统学。先知道它们是什么、解决什么问题,就够了。

    • 装饰器:本质上是“接收函数并返回新函数”的语法糖,常用于日志、鉴权、缓存、路由注册等横切逻辑。你以后在 Flask、FastAPI、pytest 里会经常见到 @xxx。
    • 闭包:指内部函数记住并继续使用外部函数作用域中的变量。它常用于“带状态的函数”、延迟执行、工厂函数。你可以把它理解成:不用类,也能把少量状态和行为绑定在一起。
    • 迭代器内部机制:核心是 iter() 和 next(),以及“一个一个地产出数据”。平时你写 for 循环时就在使用它,只是 Python 帮你隐藏了细节。理解它以后,才更容易真正看懂生成器、惰性计算和很多标准库工具。
    • 生成器:可以把它看成“会按需产生数据的函数/对象”,比一次性生成整份列表更省内存。以后你看到 yield 时,就知道它和普通 return 不一样。
    • 协程:主要用于高并发 IO 场景,比如同时发很多网络请求、下载很多网页、处理大量异步任务。它不是“更快的线程”,而是一种在单线程中高效切换等待任务的方式,典型写法会看到 async / await。
    • 多进程多线程:用于并发执行任务。一般可以粗略记住:IO 密集型任务先考虑线程或协程,CPU 密集型任务更常考虑多进程。等你真正遇到性能问题、批量处理任务、爬虫、并发下载时再深入,会更容易建立直觉。

    更好的学习顺序是:

  • 先把函数、容器、模块、异常、文件操作写熟。
  • 再写几个真实脚本,体会“代码组织”和“数据流动”。
  • 然后回头学装饰器、闭包、迭代器、生成器。
  • 最后再进并发:线程、进程、协程。
  • 这样再学这些高级主题,你不会只记住名词,而是能理解它们到底在解决什么问题。


    第 13 章 面向 AI 代码的前置语法补充

    这一章是专门按你后面要学的 AI 代码反推出来的。

    目标不是继续扩大知识点范围,而是提前把“你以后一定会反复见到的 Python 写法”单独讲清楚,这样你后面看训练代码、推理代码、Tokenizer、Dataset、Model 代码时,不会卡在语法上。

    13.1 先把后面的 AI 项目代码拆成 5 类文件来看

    你后面看到的大多数项目,代码结构其实都很像:

    • config.py:放路径、超参数、常量
    • dataset.py:准备数据、定义 Dataset / DataLoader
    • tokenizer.py:分词、编码、解码、词表
    • model.py:定义模型类
    • train.py / predict.py / evaluate.py:训练、推理、评估流程

    也就是说,后面你要面对的不是“完全陌生的 Python”,而是这些基础语法在固定模式里重复出现。

    13.2 元组解包:后面会频繁出现在 dataloader 循环里

    pair = ('Alice', 18)
    name, age = pair
    print(name, age)

    在循环里也一样:

    for inputs, targets in dataloader:
    print(inputs)
    print(targets)

    后面会怎么用到:

    • for inputs, targets in dataloader:
    • for input_tensor, target_tensor in train_dataloader:

    如果你理解成“每一轮循环都会拿到一个二元组,然后自动拆开”,就不会卡住。

    13.3 多维切片:这是看张量代码最容易卡住的点之一

    你前面已经学过切片,但后面的 AI 代码会把它写到二维、三维数据上:

    targets = data[:, 1:]
    last = output[:, –1, :]
    first_col = hidden[:, 0, :]

    先只按 Python 语法理解它:

    • 第一个 : 表示第 1 维全取
    • 1: 表示从下标 1 取到末尾
    • -1 表示最后一个位置
    • 最后一个 : 表示第 3 维全取

    后面会怎么用到:

    • targets[:, :-1]:去掉最后一个 token,作为 decoder 输入
    • targets[:, 1:]:去掉第一个 token,作为训练目标
    • output[:, -1, :]:取每个样本最后一步的输出
    • last_hidden_state[:, 0, :]:取 BERT 的 CLS 位置向量

    你现在先把它当作“多维列表切片语法”看,就能先读懂大部分模型代码。

    13.4 方法链和对象调用:不要被点号吓到

    后面 AI 代码会有大量这种写法:

    x = x.to(device)
    model = model.to(device)
    value = tensor.item()
    result = tensor.tolist()

    这本质上只是“对象调用自己的方法”:

    • obj.method()
    • 有时返回新对象
    • 有时返回普通值

    后面会怎么用到:

    • .to(device):把张量或模型放到 CPU/GPU
    • .train() / .eval():切换训练/推理模式
    • .item():把单个数值张量变成普通 Python 数字
    • .tolist():把张量转成 Python 列表
    • .reshape() / .squeeze() / .unsqueeze():调整张量形状

    所以你后面看到这种代码时,先不要急着想“深度学习数学含义”,先按“Python 对象方法调用”去读。

    13.5 squeeze、unsqueeze、reshape:先把名字和形状变化读懂

    x = x.unsqueeze(1)
    x = x.squeeze(–1)
    x = x.reshape(–1)

    你现在只需要先掌握直觉:

    • unsqueeze(dim):增加一个长度为 1 的维度
    • squeeze(dim):压掉一个长度为 1 的维度
    • reshape(…):换一种形状看同一份数据

    后面会怎么用到:

    • context_vector.unsqueeze(0):给隐藏状态补一个维度
    • output.squeeze(-1):把最后一个长度为 1 的维度压掉
    • decoder_targets.reshape(-1):拉平成一维,方便算 loss

    这部分虽然是张量操作,但卡人的第一步往往不是数学,而是没读懂 Python 调用长什么样。

    13.6 字典推导式 + 批量搬运:训练代码里特别常见

    inputs = {'a': 1, 'b': 2}
    result = {k: v * 10 for k, v in inputs.items()}
    print(result)

    后面会怎么用到:

    inputs = {k: v.to(device) for k, v in batch.items()}

    这句可以拆成三层意思:

  • 遍历字典里的每组 key, value
  • 对每个 value 调用 .to(device)
  • 再组装成一个新字典
  • 如果你能把这种推导式看顺,后面的训练代码阅读难度会下降很多。

    13.7 model(**inputs):这是“字典解包调用”,不是黑魔法

    def show(name, age):
    print(name, age)

    user = {'name': 'Alice', 'age': 18}
    show(**user)

    这和后面的:

    outputs = model(**inputs)

    是同一件事。

    意思就是:

    • inputs 是一个字典
    • 把字典里的每个键值对拆开
    • 按关键字参数的方式传给函数或模型

    后面会怎么用到:

    • BERT 模型输入字典里会有 input_ids、attention_mask、token_type_ids
    • 用 model(**inputs) 可以直接传进去,不用手写每个参数

    13.8 if __name__ == '__main__': 在后续项目里几乎是标配

    def train():
    print('start')

    if __name__ == '__main__':
    train()

    后面会怎么用到:

    • train.py 直接运行时开始训练
    • predict.py 直接运行时进入推理交互
    • dataset.py / tokenizer.py 直接运行时做小测试

    你看到这句时,脑子里只要翻译成:

    • “这个文件如果是直接运行,就执行下面这段”

    就够了。

    13.9 while True + break + continue:交互式推理脚本的固定模板

    while True:
    user_input = input('> ')
    if user_input == 'q':
    break
    if user_input.strip() == '':
    continue
    print(user_input)

    后面会怎么用到:

    • 命令行情感分析
    • 中英翻译 demo
    • 交互式输入测试

    看到这种代码时,你就按这个模板理解:

    • 一直循环
    • 输入 q 退出
    • 空输入跳过
    • 否则正常处理

    13.10 Path(__file__) + config.py:后面项目组织的核心套路

    from pathlib import Path

    ROOT_DIR = Path(__file__).parent
    DATA_DIR = ROOT_DIR / 'data'

    后面会怎么用到:

    • 定义 RAW_DATA_DIR
    • 定义 PROCESSED_DATA_DIR
    • 定义 MODELS_DIR
    • 定义 LOGS_DIR

    这类代码的价值是:

    • 让项目路径不依赖你当前命令行在哪个目录
    • 让训练、预测、评估脚本都共享一套路径配置

    所以以后你看到 config.py,不要把它当成陌生写法,它本质上就是“项目常量集中管理”。

    13.11 @classmethod / @staticmethod:后面 tokenizer 里会反复出现

    class Demo:
    @staticmethod
    def clean(text):
    return text.strip()

    @classmethod
    def from_file(cls, path):
    return cls()

    后面会怎么用到:

    • from_vocab():从词表文件创建 tokenizer
    • build_vocab():通过类方法构建词表
    • tokenize():有时会写成静态方法或类方法

    简单记法:

    • @staticmethod:和类放在一起,但不依赖实例状态
    • @classmethod:会拿到 cls,常用来做“替代构造器”

    13.12 __len__ / __getitem__:自定义数据集的关键入口

    class DemoDataset:
    def __len__(self):
    return 100

    def __getitem__(self, index):
    return index

    后面会怎么用到:

    • class ReviewAnalyzeDataset(Dataset)
    • class TranslationDataset(Dataset)

    当你看到这两个方法时,先理解成:

    • __len__:告诉外界“我有多少条数据”
    • __getitem__:告诉外界“怎么按下标取一条数据”

    这样就能读懂为什么 DataLoader 可以去遍历它。

    13.13 你后面最需要先会“读懂”的,不是所有 PyTorch,而是这几个固定模式

    你在后续 AI 学习里,最常先碰到的代码形态其实就这些:

    • device = torch.device('cuda' if … else 'cpu')
    • model = Model(…).to(device)
    • for batch in dataloader:
    • inputs = {k: v.to(device) for k, v in batch.items()}
    • outputs = model(**inputs)
    • loss.backward() / optimizer.step() / optimizer.zero_grad()
    • model.eval() + with torch.no_grad():

    你现在不用把它们全学成“框架原理”,但至少要做到:

    • Python 语法能读顺
    • 看见这些模式时不慌
    • 能分辨“这是 Python 写法”还是“这是 PyTorch API”

    13.14 这一章学完后,你的目标不是会写模型,而是做到“不在 Python 语法上掉队”

    如果你能做到下面这些,后续 AI 学习曲线就会顺很多:

    • 看到 for inputs, targets in dataloader 不慌
    • 看到 targets[:, :-1] 能知道这是切片
    • 看到 model(**inputs) 能知道这是字典解包调用
    • 看到 Path(__file__) 能知道这是项目路径定位
    • 看到 super().__init__()、__len__、__getitem__ 能知道这是类的标准写法
    • 看到 with torch.no_grad(): 能先知道它是 with 语法,不会先卡死在形式上

    13.15 本章练习

  • 写一个 while True 的小交互脚本,输入 q 退出,空字符串跳过。
  • 写一个字典推导式,把 {'a': 1, 'b': 2} 变成 {'a': 10, 'b': 20}。
  • 写一个函数,定义参数 name, age,然后用 **user 的方式调用它。
  • 写一个类,实现 __len__ 和 __getitem__。
  • 写一段切片代码,分别演示 [:, :-1]、[:, 1:]、[:, -1] 这三种形式在“二维列表语义”里的含义。

  • 第 14 章 PyTorch 最小必备:先做到能读懂训练代码

    这一章不是要把 PyTorch 讲成框架手册,而是按你后面课程代码里最常出现的模式来讲。

    目标非常明确:

    • 先能看懂 train.py、predict.py、model.py
    • 先知道一段 PyTorch 代码到底在“准备数据 / 前向传播 / 算损失 / 反向传播 / 保存模型”的哪一步
    • 先不在 tensor、shape、device、loss 这些词上卡住

    14.1 Tensor 可以先理解成“带更多能力的多维数组”

    import torch

    x = torch.tensor([[1, 2], [3, 4]], dtype=torch.float)
    print(x)
    print(x.shape)

    你现在先这样理解就够了:

    • 标量:一个数
    • 向量:一维数组
    • 矩阵:二维数组
    • Tensor:更一般化的多维数据容器

    后面会怎么用到:

    • 文本 token id 会被放进 tensor
    • 一批样本会组成二维或三维 tensor
    • 模型输入输出基本都是 tensor

    14.2 先把 shape 当成“数据的外形说明书”

    x = torch.tensor([[1, 2, 3], [4, 5, 6]])
    print(x.shape) # torch.Size([2, 3])

    这表示:

    • 有 2 行
    • 每行 3 个元素

    后面 AI 代码里你会反复看到这些名字:

    • batch_size:一批有多少样本
    • seq_len:每个样本有多少个 token
    • vocab_size:词表大小
    • hidden_size:隐藏层维度
    • embedding_dim / dim_model:向量维度

    比如:

    • [batch_size, seq_len]
    • [batch_size, seq_len, hidden_size]
    • [batch_size, vocab_size]

    后面会怎么用到:

    • review-analyze-bert/src/model.py 里会看到 last_hidden_state[:, 0, :]
    • translation-seq2seq/src/train.py 里会看到 decoder_outputs.reshape(-1, …)
    • translation-transformer/src/model.py 里会看到 [batch_size, seq_len, dim_model]

    14.3 dtype 和 device:一个管“数据类型”,一个管“放哪算”

    x = torch.tensor([1, 2, 3], dtype=torch.long)
    print(x.dtype)

    常见 dtype:

    • torch.long:整数 id,常用于 token 索引
    • torch.float:浮点数,常用于特征、loss、概率

    device 表示数据放在哪个设备上:

    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    后面会怎么用到:

    • token id tensor 通常用 long
    • 标签有时会转成 float,比如二分类的 BCEWithLogitsLoss
    • 模型和数据都要 .to(device),否则设备不一致会报错

    14.4 Dataset、DataLoader、batch:训练代码的“数据入口三件套”

    from torch.utils.data import Dataset, DataLoader

    class DemoDataset(Dataset):
    def __len__(self):
    return 100

    def __getitem__(self, index):
    return index, index + 1

    dataloader = DataLoader(DemoDataset(), batch_size=4, shuffle=True)

    可以这样理解:

    • Dataset:告诉 PyTorch“单条数据怎么取”
    • DataLoader:负责按 batch 取数据、打乱、迭代
    • batch_size:每次送给模型多少条样本

    后面会怎么用到:

    • review-analyze-rnn/src/dataset.py
    • translation-transformer/src/dataset.py
    • for inputs, targets in dataloader:

    14.5 collate_fn 和 pad_sequence:为变长序列凑成一个 batch

    from torch.nn.utils.rnn import pad_sequence

    为什么需要它:

    • 文本长度不一样
    • 一个 batch 里的句子必须整理成同样长度,才能堆叠起来

    后面会怎么用到:

    • translation-seq2seq/src/dataset.py
    • translation-transformer/src/dataset.py

    如果你后面看到:

    • collate_fn=batch_fn
    • pad_sequence(…, batch_first=True, padding_value=0)

    就先理解成:

    • “把不同长度的句子补齐后再组成 batch”

    14.6 nn.Module:PyTorch 里模型类的标准父类

    from torch import nn

    class DemoModel(nn.Module):
    def __init__(self):
    super().__init__()
    self.linear = nn.Linear(10, 2)

    def forward(self, x):
    return self.linear(x)

    你只要先记住:

    • 继承 nn.Module
    • 在 __init__ 里定义层
    • 在 forward() 里定义数据如何流动

    后面会怎么用到:

    • class ReviewAnalyzeModel(nn.Module)
    • class TranslationModel(nn.Module)
    • 你调用 model(inputs) 时,本质上是在触发 forward()

    14.7 先认识后面最常见的层

    最重要的不是背参数,而是先知道它们大概干什么。

    • nn.Embedding:把 token id 映射成向量(后面在 RNN、GRU、LSTM、Transformer 里都会用)
    • nn.Linear:线性层,常用于输出分类结果或维度变换
    • nn.RNN / nn.GRU / nn.LSTM:处理序列数据
    • nn.Transformer:Transformer 主体

    后面会怎么用到:

    • input-method-rnn/src/model.py:nn.Embedding + nn.RNN
    • review-analyze-gru/src/model.py:nn.GRU
    • review-analyze-lstm/src/model.py:nn.LSTM
    • translation-transformer/src/model.py:nn.Transformer
    • review-analyze-bert/src/model.py:AutoModel + nn.Linear

    14.8 训练循环其实就 6 步

    后面的训练代码不管换什么模型,主骨架都很像:

    model.train()
    for batch in dataloader:
    outputs = model(...)
    loss = loss_fn(outputs, targets)
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()

    你可以把它背成固定模板:

  • 切到训练模式 model.train()
  • 取一批数据
  • 做前向传播 model(…)
  • 算损失 loss_fn(…)
  • 反向传播 loss.backward()
  • 更新参数 optimizer.step(),再清梯度 optimizer.zero_grad()
  • 后面会怎么用到:

    • 几乎所有 src/train.py

    14.9 loss.backward()、optimizer.step()、zero_grad() 分别在做什么

    先用最直白的话理解:

    • loss.backward():根据 loss 反向计算梯度
    • optimizer.step():根据梯度更新参数
    • optimizer.zero_grad():把上一次梯度清掉,避免累加污染下一轮

    你现在不需要先理解求导公式,但一定要先知道这三句各自负责什么。

    14.10 train() 和 eval():同一个模型有两种工作状态

    model.train()
    model.eval()

    先记住:

    • 训练时用 train()
    • 推理/评估时用 eval()

    后面会怎么用到:

    • train.py 中:model.train()
    • predict.py、evaluate.py 中:model.eval()

    14.11 with torch.no_grad()::推理时关闭梯度

    model.eval()
    with torch.no_grad():
    outputs = model(x)

    它的作用是:

    • 推理时不记录梯度
    • 更省显存/内存
    • 更快一些

    后面会怎么用到:

    • 所有 predict.py
    • 部分 evaluate.py

    14.12 logits、概率、预测类别:别混在一起

    这是后面最容易混淆的概念之一。

    • logits:模型直接输出的原始分数
    • 概率:对 logits 做激活后得到
    • 预测类别:从概率或 logits 里挑最终结果

    常见对应关系:

    • 二分类:常看到 torch.sigmoid(output)
    • 多分类:常看到 torch.softmax(logits, dim=-1) 或直接 torch.argmax(…)

    后面会怎么用到:

    • review-analyze-bert/src/predict.py:torch.sigmoid(output)
    • translation-seq2seq/src/predict.py:torch.argmax(decoder_output, dim=-1)
    • translation-attention/src/model.py:torch.softmax(attention_scores, dim=-1)

    14.13 两种常见 loss,要先能区分场景

    后续代码里最常见的就是这两个:

    • BCEWithLogitsLoss:二分类,输入通常是 logits,标签常是 0/1
    • CrossEntropyLoss:多分类或序列分类,目标通常是类别索引

    后面会怎么用到:

    • 情感分析:BCEWithLogitsLoss
    • 翻译、输入法预测:CrossEntropyLoss

    看到 loss 名字时,你先不用深挖公式,先判断“这是二分类还是多分类/序列预测”。

    14.14 ignore_index:告诉 loss 忽略 padding 位置

    loss_fn = torch.nn.CrossEntropyLoss(ignore_index=pad_token_index)

    后面会怎么用到:

    • 翻译任务里,batch 中很多位置只是补齐用的 pad
    • 这些位置不应该参与 loss

    所以 ignore_index 的直觉是:

    • “这些位置是凑形状的,不是真实训练目标”

    14.15 保存与加载模型:先记住 state_dict

    torch.save(model.state_dict(), 'best.pt')
    model.load_state_dict(torch.load('best.pt'))

    你可以先把 state_dict 理解成:

    • 模型参数的字典快照

    后面会怎么用到:

    • 训练时保存最优模型
    • 预测时重新加载模型参数

    14.16 TensorBoard / SummaryWriter:记录训练过程

    from torch.utils.tensorboard import SummaryWriter

    writer = SummaryWriter(log_dir='logs')
    writer.add_scalar('Loss', 0.5, 1)
    writer.close()

    后面会怎么用到:

    • writer.add_scalar('Loss', loss, epoch)

    你只要先知道:

    • 它是拿来记录训练曲线的
    • 最常见记录项就是 loss

    14.17 看后续 PyTorch 代码时的阅读顺序

    建议你按这个顺序看:

  • 先看 config.py,知道路径和超参数
  • 再看 dataset.py,知道一条样本长什么样
  • 再看 model.py,知道输入输出 shape 变化
  • 再看 train.py,理解训练流程
  • 最后看 predict.py / evaluate.py
  • 这样比一上来啃 model.py 顺很多。

    14.18 本章练习

  • 用 torch.tensor() 创建一个二维 tensor,并打印它的 shape。
  • 写一个最小的 nn.Module 类,里面只放一个 Linear 层。
  • 写出一个伪训练循环,至少包含 model.train()、loss.backward()、optimizer.step()、optimizer.zero_grad()。
  • 写一段推理代码,包含 model.eval() 和 with torch.no_grad():。
  • 用一句话解释 BCEWithLogitsLoss 和 CrossEntropyLoss 各更适合什么任务。

  • 第 15 章 面向 AI 项目的最小知识地图:Tokenizer、任务、训练流程

    这一章不讲深理论,只讲你后面看 NLP / AI 项目代码时最先需要的概念地图。

    目标是:

    • 知道这些 AI 术语到底在代码里落到哪里
    • 知道一份 NLP 项目代码大概在解决什么问题
    • 不会因为概念名词太多而看不懂项目结构

    15.1 文本进入模型前,通常先经过这条流水线

    最常见的流程是:

  • 原始文本
  • tokenizer 分词/切词
  • token 转 id
  • 补齐或截断长度
  • 组成 batch
  • 喂给模型
  • 模型输出 logits / 概率 / 类别
  • 后面会怎么用到:

    • process.py
    • tokenizer.py
    • predict.py

    15.2 tokenizer 到底在做什么

    可以先把 tokenizer 理解成:

    • 把“人类文本”变成“模型能处理的 token 序列”

    常见动作:

    • tokenize():切词
    • encode():转成 id
    • decode():把 id 还原成文本

    后面会怎么用到:

    • JiebaTokenizer
    • ChineseTokenizer
    • EnglishTokenizer
    • AutoTokenizer.from_pretrained(…)

    15.3 词表 vocab 和几个特殊 token 必须认识

    后面你会经常看到:

    • unk_token:未知词
    • pad_token:补齐占位
    • sos_token:序列开始
    • eos_token:序列结束

    这些不是“语法点”,但如果不认识,后面翻译代码很容易看不懂。

    后面会怎么用到:

    • input-method-rnn/src/tokenizer.py
    • translation-transformer/src/tokenizer.py

    15.4 为什么要 padding、truncation、max_length

    因为文本长度不一样,而模型往往要求 batch 里的形状整齐。

    常见写法:

    tokenizer(text, padding='max_length', truncation=True, max_length=128)

    意思是:

    • 太短就补齐
    • 太长就截断
    • 最终都整理到同一长度

    后面会怎么用到:

    • review-analyze-bert/src/process.py
    • review-analyze-bert/src/predict.py
    • Hugging Face notebook 里的 tokenizer 示例

    15.5 attention_mask、token_type_ids 可以先知道用途,不必先深挖原理

    你后面在 BERT 输入里会看到这些字段:

    • input_ids
    • attention_mask
    • token_type_ids

    先这样理解就够:

    • input_ids:真正的 token id
    • attention_mask:哪些位置是有效内容,哪些位置是 padding
    • token_type_ids:句子对任务中区分句子 A / B

    后面会怎么用到:

    • review-analyze-bert/src/process.py
    • review-analyze-bert/src/train.py
    • review-analyze-bert/src/predict.py

    15.6 return_tensors='pt' 的意思很简单

    inputs = tokenizer(text, return_tensors='pt')

    意思就是:

    • 直接把 tokenizer 的输出整理成 PyTorch tensor 格式

    这里的 'pt' 就是 PyTorch 的缩写。

    15.7 数据集划分:train / test / valid 本质上在分工

    最基本的理解:

    • train:训练用
    • test:最后评估用
    • valid / dev:调参、挑模型用

    后面会怎么用到:

    • train_test_split(…)
    • dataset.train_test_split(…)

    你先不用纠结命名差异,只要知道“不同数据集承担不同职责”。

    15.8 你后面会遇到两类典型任务

    第一类:文本分类

    输入:一段文本
    输出:一个类别或一个分数

    后面会怎么用到:

    • 情感分析 RNN/GRU/LSTM/BERT 项目

    代码直觉通常是:

    • 输入 shape 常是 [batch_size, seq_len]
    • 输出 shape 常是 [batch_size] 或 [batch_size, num_classes]

    第二类:序列到序列任务(Seq2Seq)

    输入:一个序列
    输出:另一个序列

    后面会怎么用到:

    • 中英翻译项目
    • 输入法预测的部分思路

    代码直觉通常是:

    • 输入、输出都不是单个类别,而是一串 token

    15.9 Embedding 可以先理解成“查表取向量”

    假设:

    • token id 是 5
    • 词向量维度是 128

    那么 Embedding 做的事可以粗略理解为:

    • 去 embedding 表里拿第 5 行
    • 得到一个 128 维向量

    后面会怎么用到:

    • 所有 RNN / GRU / LSTM / Transformer 项目

    这一步不是“生成文本”,只是“把离散 id 变成可学习向量”。

    15.10 RNN、GRU、LSTM、Transformer 先知道差异层级就够了

    你现在不需要先背公式,只需要先知道:

    • RNN:最基础的序列模型
    • GRU / LSTM:为了解决长依赖问题做了改进
    • Transformer:靠注意力机制处理序列,现代大模型的核心路线
    • BERT:基于 Transformer 的预训练模型

    后面会怎么用到:

    • review-analyze-rnn
    • review-analyze-gru
    • review-analyze-lstm
    • translation-transformer
    • review-analyze-bert

    15.11 分类任务里,最后输出“分数”不一定是直接标签

    比如二分类时:

    • 模型可能先输出一个原始分数 logits
    • 再经过 sigmoid
    • 再根据阈值判断是正类还是负类

    后面会怎么用到:

    • review-analyze-bert/src/predict.py
    • review-analyze-rnn/src/predict.py

    所以你看到:

    result = torch.sigmoid(output)
    if result > 0.5:
    ...

    就知道这是“原始输出 -> 概率 -> 最终判断”的流程。

    15.12 翻译任务里,decoder_input 和 decoder_target 为什么要错一位

    后面你会看到这种写法:

    decoder_inputs = targets[:, :–1]
    decoder_targets = targets[:, 1:]

    你可以先把它理解成:

    • 输入是“到当前时刻为止已经看到的内容”
    • 目标是“下一个 token 应该是什么”

    这其实就是在训练模型做“下一个 token 预测”。

    后面会怎么用到:

    • translation-seq2seq/src/train.py
    • translation-transformer/src/train.py

    15.13 argmax 在生成任务里常表示“当前步选哪个 token”

    next_token = torch.argmax(logits, dim=–1)

    直觉上就是:

    • 从所有候选 token 里选分数最高的那个

    后面会怎么用到:

    • translation-seq2seq/src/predict.py
    • translation-transformer/src/predict.py
    • translation-attention/src/predict.py

    15.14 mask 可以先理解成“哪些位置能看,哪些位置不能看”

    后面 Transformer 代码里会看到:

    • src_pad_mask
    • tgt_mask
    • generate_square_subsequent_mask(…)

    你现在先记住它的直觉:

    • padding 的位置不要参与有效计算
    • 生成下一个 token 时,不能偷看未来位置

    先把用途看懂,比先背矩阵公式更重要。

    15.15 一份 AI 项目代码,你最该先回答这 6 个问题

    以后打开一个新项目,先问自己:

  • 这是什么任务?分类还是生成?
  • 输入是什么?文本、token id,还是张量?
  • 标签是什么?单个类别还是序列?
  • 模型最后输出的 shape 大概是什么?
  • loss 用的是什么?为什么是这个?
  • 推理时最终是怎么从输出变成结果的?
  • 如果这 6 个问题你都能回答,通常就已经不会“完全看不懂”代码了。

    15.16 学到这里,你后续更该区分两件事

    第一件:这是 Python 语法问题。

    比如:

    • **inputs
    • 切片
    • for … in …
    • 类继承

    第二件:这是 AI / PyTorch 框架问题。

    比如:

    • 为什么用 CrossEntropyLoss
    • 为什么要 padding
    • 为什么要 attention_mask
    • 为什么 Embedding 维度这样设

    把这两类问题分开,你学习时就不会一团乱麻。

    15.17 本章练习

  • 用自己的话解释:token、vocab、token id 三者关系。
  • 用一句话说明 padding='max_length'、truncation=True、max_length=128 各在做什么。
  • 解释为什么翻译训练里会写 targets[:, :-1] 和 targets[:, 1:]。
  • 说明文本分类和序列生成在“输出形式”上的主要区别。
  • 打开一个后续项目的 config.py、dataset.py、model.py、train.py,分别写一句它们的职责。

  • 第 16 章 后续课程代码阅读导航:先看什么,再看什么

    这一章专门解决一个现实问题:

    • 文档你已经学了
    • 后面的 AI 项目代码也摆在那里
    • 但一打开项目,还是容易不知道“第一眼该看哪儿”

    所以这里不再讲泛知识点,而是直接告诉你:

    • 一个项目先看什么
    • 每个文件在干什么
    • 哪些地方是 Python 语法,哪些地方是 PyTorch / AI 框架知识

    16.1 先记住一个通用阅读顺序

    以后你打开一个新项目,建议固定按这个顺序:

  • config.py
  • dataset.py / process.py
  • tokenizer.py
  • model.py
  • train.py
  • predict.py
  • evaluate.py
  • 原因很简单:

    • config.py 决定路径和超参数
    • dataset.py / process.py 决定数据长什么样
    • tokenizer.py 决定文本怎么变 token / id
    • model.py 决定模型结构
    • train.py 决定训练流程
    • predict.py / evaluate.py 决定推理和评估怎么跑

    不要一上来就啃 model.py,那样最容易迷路。

    16.2 先看情感分析项目:它最适合当第一个完整 AI 代码样板

    建议优先看这组:

    • 尚硅谷大模型智能体线上速成班2026年01月11【itjc8.com】/代码/review-analyze-rnn/src/
    • 尚硅谷大模型智能体线上速成班2026年01月11【itjc8.com】/代码/review-analyze-gru/src/
    • 尚硅谷大模型智能体线上速成班2026年01月11【itjc8.com】/代码/review-analyze-lstm/src/
    • 尚硅谷大模型智能体线上速成班2026年01月11【itjc8.com】/代码/review-analyze-bert/src/

    为什么先看它:

    • 任务清晰:输入一段文本,输出正/负情感
    • 输出简单:不是生成一串文本,而是输出一个分数或类别
    • 结构完整:包含数据处理、模型、训练、预测、评估
    • 能把 Python + PyTorch + NLP 的基础工作流一口气串起来

    16.3 情感分析项目的阅读顺序

    建议这样看:

  • config.py
  • process.py
  • dataset.py
  • tokenizer.py
  • model.py
  • train.py
  • predict.py
  • evaluate.py
  • 你每看一个文件,就回答一句:

    • 这个文件负责数据、模型,还是流程?

    16.4 情感分析项目里每个文件在干嘛

    config.py

    • 放目录路径、SEQ_LEN、BATCH_SIZE、LEARNING_RATE 这些超参数
    • 你会看到 Path(__file__) 和路径拼接

    process.py

    • 负责原始数据读取、清洗、切分训练集/测试集、tokenize 或 encode
    • 你会看到 train_test_split、lambda、padding='max_length'、truncation=True

    dataset.py

    • 负责把一条条样本包装成 Dataset
    • 你会看到 __len__、__getitem__、DataLoader

    tokenizer.py

    • 负责词表构建、文本切词、id 编码、词表文件读写
    • 你会看到 @classmethod、@staticmethod、word2index.get()、列表推导式

    model.py

    • 定义模型结构
    • 你会看到 nn.Module、nn.Embedding、nn.RNN / nn.GRU / nn.LSTM / AutoModel

    train.py

    • 定义训练循环
    • 你会看到 model.train()、loss.backward()、optimizer.step()、optimizer.zero_grad()、SummaryWriter

    predict.py

    • 定义单条或批量推理
    • 你会看到 model.eval()、with torch.no_grad():、torch.sigmoid()、while True

    evaluate.py

    • 负责整体验证指标
    • 你会看到把预测结果和标签收集起来再做评估

    16.5 情感分析项目里,哪些地方最容易卡住

    最容易卡你的点通常不是“模型原理”,而是这些:

    • inputs = {k: v.to(device) for k, v in batch.items()}
    • labels = inputs.pop('labels')
    • outputs = model(**inputs)
    • torch.sigmoid(output)
    • BCEWithLogitsLoss

    如果这些你已经在前面章节看顺了,情感分析项目就会容易很多。

    16.6 第二个看 Seq2Seq 翻译:它会让你真正进入“序列生成”思维

    建议接着看:

    • 尚硅谷大模型智能体线上速成班2026年01月11【itjc8.com】/代码/translation-seq2seq/src/

    为什么第二个看它:

    • 比分类任务更复杂,但比 Transformer 更容易入门
    • 你会第一次系统接触“输入序列 -> 输出序列”
    • 能帮你理解 decoder_input、decoder_target、自回归生成这些概念

    16.7 Seq2Seq 项目先看什么

    建议顺序:

  • config.py
  • tokenizer.py
  • process.py
  • dataset.py
  • model.py
  • train.py
  • predict.py
  • evaluate.py
  • 这里把 tokenizer.py 提前,是因为翻译任务里 tokenizer 和特殊 token 特别关键。

    16.8 Seq2Seq 项目里最该盯住的几个点

    看代码时重点盯这几个地方:

    • sos_token / eos_token / pad_token
    • decoder_inputs = targets[:, :-1]
    • decoder_targets = targets[:, 1:]
    • torch.cat(…)
    • argmax(…)
    • CrossEntropyLoss(ignore_index=…)

    你要先能把这些代码翻译成自然语言:

    • “输入是前半段,目标是下一步”
    • “每一轮生成一个 token,再拼接起来”
    • “pad 位置不算 loss”

    16.9 第三个看 Transformer 翻译:它更接近后面大模型思维

    建议再看:

    • 尚硅谷大模型智能体线上速成班2026年01月11【itjc8.com】/代码/translation-transformer/src/

    为什么第三个看它:

    • 结构比 Seq2Seq 更抽象
    • 会引入位置编码、mask、Transformer encoder/decoder
    • 更接近你后面理解大模型和注意力机制的代码入口

    16.10 Transformer 项目里,第一轮重点只盯这几件事

    先别急着深究公式,第一轮只要盯住:

    • nn.Transformer
    • PositionEncoding
    • src_pad_mask
    • tgt_mask
    • generate_square_subsequent_mask(…)
    • memory = encoder(…)
    • decode(…)

    先把这些代码在“流程上”看懂:

    • 输入先编码
    • decoder 逐步生成
    • mask 控制哪些位置能看、哪些位置不能看

    16.11 input-method-rnn 项目适合拿来练手“最小训练闭环”

    这个项目也值得看:

    • 尚硅谷大模型智能体线上速成班2026年01月11【itjc8.com】/代码/input-method-rnn/src/

    它的价值是:

    • 结构简单
    • tokenizer、dataset、model、train、predict 都比较直白
    • 非常适合拿来练“我能不能顺着读完一套训练代码”

    如果你觉得 BERT 或 Transformer 太重,可以先拿它热身。

    16.12 Hugging Face 相关内容建议怎么读

    你后面还会看到:

    • AutoTokenizer.from_pretrained(…)
    • AutoModel.from_pretrained(…)
    • load_dataset(…)

    这些最容易让人误以为“我是不是先得把 Hugging Face 全学完”。

    其实不用。

    第一轮你只要先理解:

    • 它是在帮你少写底层细节
    • AutoTokenizer 帮你处理 tokenization
    • AutoModel 帮你加载预训练模型
    • load_dataset 帮你读取和组织数据集

    先把它们当成“高级工具函数”去读就够了。

    16.13 你后续读代码时,先分清“这是语法问题还是框架问题”

    看到一行代码时,先问自己:

    • 这是 Python 写法不懂?
    • 还是 PyTorch API 不懂?
    • 还是任务逻辑不懂?

    举例:

    • model(**inputs):主要是 Python 语法
    • CrossEntropyLoss(ignore_index=…):主要是 PyTorch / 任务知识
    • targets[:, 1:]:主要是 Python 切片 + 张量 shape
    • generate_square_subsequent_mask:主要是 Transformer 任务逻辑

    把问题拆开,你学习速度会快很多。

    16.14 每个项目第一轮只做“4 件事”

    不要试图第一次就把所有细节啃完。第一轮只做这 4 件事:

  • 说清楚任务是什么
  • 说清楚输入输出各是什么
  • 说清楚训练脚本主流程
  • 说清楚推理脚本怎么把结果打出来
  • 只要这 4 件事能说清,后面第二轮再回来看细节会容易很多。

    16.15 本章练习

  • 在 review-analyze-bert 项目里,按顺序打开 config.py、process.py、dataset.py、model.py、train.py,各写一句“这个文件负责什么”。
  • 在 translation-seq2seq 项目里,找到 decoder_inputs = targets[:, :-1] 和 decoder_targets = targets[:, 1:],用自然语言解释它们。
  • 在 translation-transformer 项目里,找到 src_pad_mask 和 tgt_mask,先不讲数学,只说明“它们分别是为了防什么问题”。
  • 任选一个 predict.py,把交互循环部分完整讲一遍。

  • 第 17 章 术语速查表:后续 AI / PyTorch 学习高频词一页通

    这一章不是教程,而是速查表。

    以后你看代码、看笔记、看课程视频时,看到这些词可以快速回来查,不用每次都重新搜。

    17.1 Tensor

    • 多维数据容器
    • 可以先把它理解成“带计算能力的多维数组”
    • 后面模型输入输出基本都是它

    17.2 shape

    • 数据外形
    • 比如 [batch_size, seq_len]
    • 是理解模型代码最重要的线索之一

    17.3 batch / batch_size

    • 一批样本
    • batch_size 表示一批包含多少条数据
    • 训练通常不是一条一条跑,而是一批一批跑

    17.4 seq_len

    • 序列长度
    • 在 NLP 里通常表示一句话有多少 token

    17.5 vocab / vocab_size

    • 词表 / 词表大小
    • 词表把 token 映射成 id

    17.6 token / token id

    • token:切分后的最小文本单位
    • token id:token 对应的整数编号

    17.7 tokenizer

    • 把文本转成 token / id 的工具
    • 有时也负责把 id 还原成文本

    17.8 padding

    • 补齐
    • 把不同长度样本补到一致长度,方便组成 batch

    17.9 truncation

    • 截断
    • 文本太长时裁剪掉后面一部分

    17.10 max_length

    • 最大长度
    • 常与 padding / truncation 一起出现

    17.11 attention_mask

    • 标记哪些位置是真实内容,哪些位置是 padding
    • BERT 输入里很常见

    17.12 token_type_ids

    • 区分句子 A / 句子 B 的输入标记
    • 在句对任务里更常见

    17.13 return_tensors=‘pt’

    • tokenizer 输出直接转成 PyTorch tensor
    • 'pt' 就是 PyTorch

    17.14 Dataset

    • 单条数据如何取出来的定义
    • 通常配合 __len__ 和 __getitem__

    17.15 DataLoader

    • 按 batch 提供数据
    • 可以打乱、迭代、拼 batch

    17.16 collate_fn

    • 自定义“一个 batch 怎么拼出来”
    • 处理变长序列时很常见

    17.17 pad_sequence

    • 把不同长度序列补齐后再拼成 batch
    • 翻译任务里很常见

    17.18 nn.Module

    • PyTorch 模型类的标准父类
    • 你定义模型通常都要继承它

    17.19 forward

    • 定义前向传播逻辑的方法
    • 决定输入怎么流到输出

    17.20 Embedding

    • 把 token id 映射成向量
    • 可以先理解成“查表取向量”

    17.21 hidden_size / embedding_dim / dim_model

    • 都是向量维度相关参数
    • 名字不同,但本质都在描述“表示空间大小”

    17.22 logits

    • 模型直接输出的原始分数
    • 不是最终概率

    17.23 sigmoid

    • 常用于二分类,把 logits 映射到 0 到 1

    17.24 softmax

    • 常用于多分类或注意力权重归一化
    • 把一组分数变成概率分布

    17.25 argmax

    • 取最大值所在位置
    • 常用于“选当前最可能的类别 / token”

    17.26 BCEWithLogitsLoss

    • 常用于二分类
    • 输入通常是 logits,不需要你先手动做 sigmoid 再喂给 loss

    17.27 CrossEntropyLoss

    • 常用于多分类或序列预测
    • 翻译、输入法预测里经常见到

    17.28 ignore_index

    • 告诉 loss 忽略某些目标位置
    • 通常用来忽略 pad token

    17.29 optimizer

    • 优化器
    • 负责根据梯度更新模型参数

    17.30 loss.backward()

    • 反向传播
    • 计算梯度

    17.31 optimizer.step()

    • 更新参数

    17.32 optimizer.zero_grad()

    • 清空旧梯度
    • 避免梯度累计污染下一轮

    17.33 model.train() / model.eval()

    • train():训练模式
    • eval():评估/推理模式

    17.34 torch.no_grad()

    • 推理时关闭梯度记录
    • 节省资源

    17.35 state_dict

    • 模型参数字典快照
    • 训练保存、预测加载时都会用到

    17.36 SummaryWriter / TensorBoard

    • 用来记录训练过程,比如 loss 曲线

    17.37 RNN / GRU / LSTM

    • 经典序列模型
    • GRU、LSTM 是 RNN 的改进版

    17.38 Transformer

    • 基于注意力机制的序列模型
    • 大模型路线的核心基础之一

    17.39 BERT

    • 基于 Transformer 的预训练语言模型
    • 你后面课程里的情感分析项目会用到

    17.40 mask

    • 控制哪些位置参与计算、哪些位置被遮住
    • Transformer 里非常关键

    17.41 config.py

    • 项目配置入口
    • 常放路径、超参数、常量

    17.42 train.py / predict.py / evaluate.py

    • train.py:训练
    • predict.py:推理/交互
    • evaluate.py:评估

    17.43 Python 语法问题 vs 框架问题

    以后卡住时先问自己:

    • 这是 Python 语法不懂?
    • 还是 PyTorch API 不懂?
    • 还是任务逻辑不懂?

    先把问题归类,学习效率会高很多。


    第 18 章 学完这份教程以后,下一步怎么练

    建议直接做 4 类小练习:

    18.1 命令行小工具

    比如:

    • 记账脚本
    • 批量重命名文件
    • 文本统计
    • CSV 清洗

    18.2 文件处理脚本

    比如:

    • 批量读取目录中的文件
    • 替换文本
    • 合并 Markdown
    • 导出结果到新文件

    18.3 数据结构练习

    比如:

    • 学生成绩统计
    • 单词频次统计
    • 商品库存统计

    18.4 简单面向对象练习

    比如:

    • 学生管理系统
    • 图书借阅系统
    • 订单对象与支付对象建模

    第 19 章 一页速记

    name = 'Alice'
    age = 18

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

    nums = [1, 2, 3]
    user = {'name': 'Alice', 'age': 18}
    tags = {'python', 'java'}

    for n in nums:
    print(n)

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

    class Person:
    def __init__(self, name: str):
    self.name = name

    def speak(self) –> None:
    print(self.name)

    with open('a.txt', 'rt', encoding='utf-8') as f:
    print(f.read())


    最后给 Java 开发者的建议

    真正阻碍你学 Python 的,通常不是“语法记不住”,而是这几种惯性:

    • 总想先设计完整类型体系
    • 总想把代码写成 Java 的组织方式
    • 总想先把高级特性学完再动手

    更好的顺序是:

  • 先能写脚本
  • 再能写小项目
  • 再逐步学 Pythonic 写法
  • 最后再补高级机制
  • 如果你愿意,把这份教程当成第一轮学习主线,把完整原稿当成“查漏补缺的参考书”,效果会比直接啃原始大而全资料更好。

    赞(0)
    未经允许不得转载:171主机测评 » Python 入门教程(面向有 Java 经验的开发者)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址