Skip to content

Python 语法与常用包


Python — Guido van Rossum, 1991

Python is a programming language that lets you work quickly and integrate systems more effectively.

Python 是一门让你能够快速开发并高效整合系统的编程语言。它是机器学习与人工智能领域最主流的编程语言,几乎所有深度学习框架都以 Python 为主要接口。


基础语法

变量与数据类型

Python 是动态类型语言,变量不需要声明类型,赋值即创建。

# 基本数据类型
x = 42              # int 整数
y = 3.14            # float 浮点数
name = "疾旋鼬"     # str 字符串
is_cute = True      # bool 布尔值
nothing = None      # NoneType 空值

# 查看类型
print(type(x))      # <class 'int'>
print(type(y))      # <class 'float'>
print(type(name))   # <class 'str'>
print(type(is_cute))# <class 'bool'>

Python 3 中,int 没有大小限制,可以表示任意大的整数:

big_number = 10 ** 100  # 10 的 100 次方,googol
print(big_number)       # 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

类型转换

# 显式类型转换
s = "123"
n = int(s)          # 字符串 → 整数: 123
f = float(s)        # 字符串 → 浮点数: 123.0
s2 = str(n)         # 整数 → 字符串: "123"

# 浮点数与整数互转
a = int(3.9)        # 3 (截断,不是四舍五入)
b = float(3)        # 3.0

字符串操作

# 字符串是不可变的序列类型
s = "Hello, 疾旋鼬"

# 索引与切片(从 0 开始)
print(s[0])         # 'H'
print(s[-1])        # '鼬'(负索引从末尾开始)
print(s[0:5])       # 'Hello'(左闭右开区间)

# 常用方法
print(s.lower())    # 'hello, 疾旋鼬'
print(s.upper())    # 'HELLO, 疾旋鼬'
print(s.replace('Hello', 'Hi'))  # 'Hi, 疾旋鼬'
print(s.split(', '))# ['Hello', '疾旋鼬']
print(len(s))       # 10

# f-string 格式化(Python 3.6+)
name = "疾旋鼬"
age = 1
print(f"{name}今年{age}岁")         # '疾旋鼬今年1岁'
print(f"{3.14159:.2f}")             # '3.14'(保留两位小数)
print(f"{'居中':^10}")              # '    居中    '(居中对齐)

# 多行字符串
poem = """
疾旋鼬,
蜷缩旋转,
速度惊人。
"""

运算符

# 算术运算符
print(7 + 3)    # 10  加法
print(7 - 3)    # 4   减法
print(7 * 3)    # 21  乘法
print(7 / 3)    # 2.3333...  除法(结果总是 float)
print(7 // 3)   # 2   整除(向下取整)
print(7 % 3)    # 1   取模(余数)
print(7 ** 3)   # 343 幂运算

# 比较运算符(返回 bool)
print(3 == 3)   # True   等于
print(3 != 4)   # True   不等于
print(3 > 2)    # True   大于
print(3 <= 3)   # True   小于等于

# 逻辑运算符
print(True and False)   # False  与
print(True or False)    # True   或
print(not True)         # False  非

# 身份运算符(判断是否是同一个对象)
a = [1, 2, 3]
b = a
c = [1, 2, 3]
print(a is b)       # True  (b 指向同一个对象)
print(a is c)       # False (c 是新创建的对象)
print(a == c)       # True  (值相等)

# 成员运算符
print(3 in [1, 2, 3])         # True
print('疾' in '疾旋鼬')       # True

# 链式比较
x = 5
print(1 < x < 10)             # True

条件语句

score = 85

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 70:
    grade = "C"
else:
    grade = "D"

print(f"成绩: {grade}")  # 成绩: B

elif 是 else if 的缩写。条件判断从上到下,执行第一个满足条件的分支后跳过其余分支。

循环

for 循环

# 遍历列表
animals = ["疾旋鼬", "捣蛋猫", "桃旋鼬"]
for animal in animals:
    print(animal)

# range(start, stop, step) 生成整数序列
for i in range(5):          # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 8, 2):    # 2, 4, 6
    print(i)

# enumerate 同时获取索引和值
for i, animal in enumerate(animals):
    print(f"{i}: {animal}")
# 0: 疾旋鼬
# 1: 捣蛋猫
# 2: 桃旋鼬

# zip 并行遍历多个序列
names = ["疾旋鼬", "捣蛋猫"]
types = ["龙", "无"]
for name, t in zip(names, types):
    print(f"{name} 是 {t} 属性")

while 循环

n = 10
while n > 0:
    print(n)
    n -= 1
print("发射!")

break 与 continue

# break: 立即退出整个循环
for i in range(10):
    if i == 5:
        break           # 当 i=5 时退出
    print(i)            # 输出 0 1 2 3 4

# continue: 跳过当前迭代,进入下一次
for i in range(10):
    if i % 2 == 0:
        continue        # 跳过偶数
    print(i)            # 输出 1 3 5 7 9

List Comprehension

列表推导式(List Comprehension)是 Python 中创建列表的简洁方式,在机器学习代码中极其常用。

# 基本语法: [表达式 for 变量 in 可迭代对象]
squares = [x**2 for x in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 带条件过滤: [表达式 for 变量 in 可迭代对象 if 条件]
evens = [x for x in range(20) if x % 2 == 0]
print(evens)    # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# 嵌套推导: 展平二维列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
print(flat)     # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 带表达式的推导
labels = [0, 1, 2, 1, 0]
one_hot = [[1 if i == l else 0 for i in range(3)] for l in labels]
print(one_hot)  # [[1,0,0], [0,1,0], [0,0,1], [0,1,0], [1,0,0]]

数据结构

列表(list)

列表是有序、可变的序列,是 Python 中最常用的数据结构。

# 创建列表
fruits = ["疾旋鼬", "捣蛋猫", "桃旋鼬"]

# 索引与切片
print(fruits[0])        # '疾旋鼬'
print(fruits[-1])       # '桃旋鼬'
print(fruits[0:2])      # ['疾旋鼬', '捣蛋猫']

# 修改元素
fruits[1] = "火绒狐"
print(fruits)           # ['疾旋鼬', '火绒狐', '桃旋鼬']

# 添加元素
fruits.append("冰刺猬")         # 末尾添加
fruits.insert(1, "雷角鹿")      # 在索引 1 处插入
fruits.extend(["风灵龙", "水灵猫"])  # 扩展列表

# 删除元素
fruits.remove("桃旋鼬")         # 按值删除
popped = fruits.pop()           # 弹出末尾元素
del fruits[0]                   # 按索引删除

# 排序
numbers = [3, 1, 4, 1, 5, 9]
numbers.sort()                  # 原地排序: [1, 1, 3, 4, 5, 9]
numbers.sort(reverse=True)      # 降序: [9, 5, 4, 3, 1, 1]
sorted_nums = sorted(numbers)   # 返回新列表,不修改原列表

# 列表复制(注意浅拷贝与深拷贝)
a = [1, 2, [3, 4]]
b = a               # 浅拷贝: b 和 a 指向同一对象
c = a.copy()        # 浅拷贝: 新列表,但内部列表仍共享
import copy
d = copy.deepcopy(a)# 深拷贝: 完全独立的副本

# 常用操作
print(len(fruits))          # 列表长度
print(fruits.count("疾旋鼬")) # 统计出现次数
print(fruits.index("疾旋鼬")) # 查找第一次出现的索引

浅拷贝与深拷贝

在 Python 中,列表复制涉及浅拷贝和深拷贝,理解它们的区别对于避免意外的数据修改非常重要。

a = [1, 2, [3, 4]]  # 初始列表

直接赋值

b = a
- b 是 a 的别名,两者指向同一个对象 - 修改其中一个会同时影响另一个
b.append(5)
print(a)  # [1, 2, [3, 4], 5]

浅拷贝

c = a.copy()  # 或 a[:] 或 list(a)
- 创建新列表,但内嵌元素仍是原列表元素的引用 - 修改不可变元素(如整数)不会相互影响 - 修改可变元素(如内嵌列表)会相互影响
a[0] = 100        # 修改整数,c 不变
a[2].append(5)    # 修改内嵌列表,c 也会变化
print(a)          # [100, 2, [3, 4, 5]]
print(c)          # [1, 2, [3, 4, 5]]

深拷贝

import copy
d = copy.deepcopy(a)
  • 递归复制所有对象,创建完全独立的副本
  • 修改任何元素都不会相互影响
a[2].append(6)
print(a)          # [100, 2, [3, 4, 5, 6]]
print(d)          # [100, 2, [3, 4, 5]]

元组(tuple)

元组是有序、不可变的序列。一旦创建,不能修改。

# 创建元组
point = (3, 4)
single = (42,)      # 单元素元组需要逗号
empty = ()

# 元组解包
x, y = point
print(x, y)         # 3 4

# 交换变量(利用元组解包)
a, b = 1, 2
a, b = b, a         # a=2, b=1

# 元组作为字典的键(因为不可变)
locations = {
    (0, 0): "起点",
    (3, 4): "疾旋鼬的家",
}

字典(dict)

字典是键值对的无序集合(Python 3.7+ 保持插入顺序)。

# 创建字典
pal = {
    "name": "疾旋鼬",
    "type": "龙",
    "hp": 100,
    "skills": ["旋转冲击", "蜷缩防御"],
}

# 访问元素
print(pal["name"])              # '疾旋鼬'
print(pal.get("mp", 0))        # 0(键不存在时返回默认值)

# 修改与添加
pal["hp"] = 120                 # 修改
pal["attack"] = 85              # 添加新键

# 删除
del pal["attack"]
removed = pal.pop("skills")     # 弹出并返回

# 遍历
for key, value in pal.items():
    print(f"{key}: {value}")

for key in pal.keys():
    print(key)

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

# 字典推导式
squares = {x: x**2 for x in range(6)}
print(squares)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# 合并字典(Python 3.9+)
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
d3 = d1 | d2        # {'a': 1, 'b': 3, 'c': 4}(后者覆盖前者)

集合(set)

集合是无序、不重复的元素集合,常用于去重和集合运算。

# 创建集合
types = {"龙", "火", "水", "龙"}  # 自动去重
print(types)        # {'龙', '火', '水'}

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

# 集合推导式
evens = {x for x in range(20) if x % 2 == 0}

函数

# 基本函数定义
def greet(name):
    """问候函数(这是 docstring,文档字符串)"""
    return f"你好,{name}!"

print(greet("疾旋鼬"))  # 你好,疾旋鼬!

# 默认参数
def power(base, exp=2):
    return base ** exp

print(power(3))       # 9 (使用默认 exp=2)
print(power(3, 3))    # 27

# 可变参数 *args(接收任意数量的位置参数,打包为元组)
def mean(*numbers):
    return sum(numbers) / len(numbers)

print(mean(1, 2, 3, 4, 5))  # 3.0

# 关键字可变参数 **kwargs(接收任意数量的关键字参数,打包为字典,参数key=value 形式)
def build_model(**kwargs):
    for key, value in kwargs.items():
        print(f"{key} = {value}")

build_model(d_model=512, num_heads=8, d_ff=2048)

# 参数组合顺序: 位置参数 → 默认参数 → *args → **kwargs
def transformer_forward(x, mask=None, *layers, **config):
    pass

# Lambda 匿名函数(常用于简短的函数定义)
square = lambda x: x ** 2
print(square(5))  # 25

# 函数是一等公民,可以作为参数传递
def apply(func, value):
    return func(value)

print(apply(square, 4))        # 16
print(apply(lambda x: x + 1, 4))  # 5

类与面向对象编程

Python 中一切皆对象。类是创建对象的蓝图。

class Pal:
    """帕鲁(游戏中的生物)的基类"""

    # 类变量(所有实例共享)
    kingdom = "帕鲁世界"

    def __init__(self, name, element, hp=100):
        """构造函数,创建实例时自动调用"""
        # 实例变量(每个实例独有)
        self.name = name
        self.element = element
        self.hp = hp
        self._secret = "内部变量"   # 单下划线:约定为"私有"(但不强制)
        self.__hidden = "真正私有"  # 双下划线:名称改写(name mangling)

    def attack(self):
        """实例方法:第一个参数必须是 self"""
        return f"{self.name} 发动攻击!"

    def take_damage(self, damage):
        self.hp -= damage
        if self.hp <= 0:
            self.hp = 0
            print(f"{self.name} 倒下了!")

    @property
    def is_alive(self):
        """属性装饰器:像属性一样访问,但有计算逻辑"""
        return self.hp > 0

    @staticmethod
    def is_valid_element(element):
        """静态方法:不需要实例,不接收 self"""
        valid = {"龙", "火", "水", "草", "电", "冰"}
        return element in valid

    @classmethod
    def from_dict(cls, data):
        """类方法:接收类本身作为第一个参数(cls),常用于替代构造函数"""
        return cls(data["name"], data["element"], data["hp"])

    def __str__(self):
        """定义 print() 时的输出"""
        return f"Pal({self.name}, {self.element}, HP={self.hp})"

    def __repr__(self):
        """定义在交互式环境中的显示(更详细)"""
        return f"Pal(name='{self.name}', element='{self.element}', hp={self.hp})"

    def __len__(self):
        """定义 len() 的行为"""
        return self.hp


# 使用
jxy = Pal("疾旋鼬", "龙", 120)
print(jxy)                  # Pal(疾旋鼬, 龙, HP=120)
print(jxy.attack())         # 疾旋鼬 发动攻击!
print(jxy.is_alive)         # True
print(Pal.is_valid_element("龙"))  # True

# 从字典创建
data = {"name": "桃旋鼬", "element": "龙", "hp": 90}
txy = Pal.from_dict(data)
print(txy)                  # Pal(桃旋鼬, 龙, HP=90)

继承

class DragonPal(Pal):
    """龙属性帕鲁,继承自 Pal"""

    def __init__(self, name, hp=100, dragon_power=50):
        # 调用父类构造函数
        super().__init__(name, "龙", hp)
        self.dragon_power = dragon_power

    def attack(self):
        """重写父类方法"""
        return f"{self.name} 发动龙之怒!(威力: {self.dragon_power})"

    def fly(self):
        """子类独有方法"""
        return f"{self.name} 展翅高飞!"


dragon = DragonPal("疾旋鼬", 120, 80)
print(dragon.attack())      # 疾旋鼬 发动龙之怒!(威力: 80)
print(dragon.fly())         # 疾旋鼬 展翅高飞!
print(dragon.is_alive)      # True(继承的属性装饰器仍然可用)

# isinstance 判断类型
print(isinstance(dragon, DragonPal))  # True
print(isinstance(dragon, Pal))        # True(子类实例也是父类实例)

多重继承与 Mixin

class Flyable:
    def fly(self):
        return f"{self.name} 在飞!"

class Swimmable:
    def swim(self):
        return f"{self.name} 在游泳!"

class WaterDragonPal(Pal, Flyable, Swimmable):
    """多重继承:同时获得多个类的能力"""
    pass

wd = WaterDragonPal("海龙", "水", 150)
print(wd.fly())     # 海龙 在飞!
print(wd.swim())    # 海龙 在游泳!

异常处理

try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(f"错误: {e}")           # 错误: division by zero
except (TypeError, ValueError) as e:
    print(f"类型或值错误: {e}")    # 可以同时捕获多种异常
else:
    print("没有异常时执行")
finally:
    print("无论是否异常都执行")    # 常用于清理资源

# 自定义异常
class ModelNotFoundError(Exception):
    pass

# 抛出异常
def load_model(path):
    import os
    if not os.path.exists(path):
        raise ModelNotFoundError(f"模型文件不存在: {path}")
    return "model"

# 上下文管理器(with 语句)
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()
# 离开 with 块后,文件自动关闭

模块与导入

# 导入整个模块
import math
print(math.sqrt(16))        # 4.0

# 导入特定函数
from math import sqrt, log
print(sqrt(16))             # 4.0

# 导入并重命名
import numpy as np
from torch.nn import functional as F

# 导入模块中的所有(不推荐,容易命名冲突)
from math import *

# 自定义模块
# 假设有一个文件 utils.py,其中定义了 function hello()
# import utils
# from utils import hello

文件操作

# 读取文件
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()              # 读取全部内容
    # 或逐行读取
    for line in f:
        print(line.strip())

# 写入文件
with open("output.txt", "w", encoding="utf-8") as f:
    f.write("疾旋鼬\n")
    f.write("捣蛋猫\n")

# 追加写入
with open("output.txt", "a", encoding="utf-8") as f:
    f.write("桃旋鼬\n")

# 读写 JSON
import json
data = {"name": "疾旋鼬", "hp": 100}
with open("pal.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

with open("pal.json", "r", encoding="utf-8") as f:
    loaded = json.load(f)
    print(loaded)  # {'name': '疾旋鼬', 'hp': 100}

数值计算基础:NumPy

NumPy 是 Python 科学计算的基石,提供了高效的多维数组对象和大量数学函数。理解 NumPy 是使用 PyTorch 等深度学习框架的前提。

为什么需要 NumPy?

Python 原生的列表虽然灵活,但存储和计算效率极低。NumPy 数组在内存中连续存储,底层用 C 实现,运算速度比纯 Python 快 10-100 倍。在机器学习中,数据几乎总是以数组(张量)的形式存在,NumPy 提供了操作这些数据的所有基础工具。

数组创建

import numpy as np

# 从列表创建
a = np.array([1, 2, 3, 4, 5])          # 一维数组
b = np.array([[1, 2, 3], [4, 5, 6]])   # 二维数组(矩阵)

# 常用创建函数
zeros = np.zeros((3, 4))        # 3×4 全零矩阵
ones = np.ones((2, 3))          # 2×3 全一矩阵
eye = np.eye(4)                 # 4×4 单位矩阵
arange = np.arange(0, 10, 2)    # [0, 2, 4, 6, 8](类似 range)
linspace = np.linspace(0, 1, 5) # [0, 0.25, 0.5, 0.75, 1](等间隔)
random_normal = np.random.randn(3, 4)    # 标准正态分布随机数
random_uniform = np.random.rand(3, 4)    # [0, 1) 均匀分布随机数
random_int = np.random.randint(0, 10, (3, 4))  # 随机整数

# 数组属性
print(a.shape)      # (5,)       形状
print(b.shape)      # (2, 3)     形状
print(b.ndim)       # 2          维度数
print(b.size)       # 6          元素总数
print(b.dtype)      # int64      数据类型

数组运算

NumPy 的核心特性是向量化运算——不需要显式循环,直接对整个数组进行运算。

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

# 逐元素运算(element-wise)
print(a + b)        # [5, 7, 9]      加法
print(a - b)        # [-3, -3, -3]   减法
print(a * b)        # [4, 10, 18]    逐元素乘法
print(a / b)        # [0.25, 0.4, 0.5]  除法
print(a ** 2)       # [1, 4, 9]      幂运算
print(np.sqrt(a))   # [1.0, 1.414, 1.732]  平方根
print(np.exp(a))    # [2.718, 7.389, 20.086]  指数
print(np.log(a))    # [0.0, 0.693, 1.099]  自然对数

# 聚合运算
print(np.sum(a))    # 6      求和
print(np.mean(a))   # 2.0    均值
print(np.std(a))    # 0.816  标准差
print(np.max(a))    # 3      最大值
print(np.min(a))    # 1      最小值
print(np.argmax(a)) # 2      最大值索引

# 矩阵运算
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

# 矩阵乘法(三种等价写法)
C1 = A @ B              # [[19, 22], [43, 50]]  推荐
C2 = np.dot(A, B)       # 同上
C3 = A.dot(B)           # 同上

# 转置
print(A.T)              # [[1, 3], [2, 4]]

# 点积(向量内积)
v1 = np.array([1, 2, 3])
v2 = np.array([4, 5, 6])
print(np.dot(v1, v2))   # 32 = 1*4 + 2*5 + 3*6

索引与切片

A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])

# 基本索引
print(A[0, 1])      # 2    第0行第1列
print(A[1, :])      # [4, 5, 6]    第1行所有列
print(A[:, 2])      # [3, 6, 9]    所有行第2列

# 切片
print(A[0:2, 1:3])  # [[2, 3], [5, 6]]    子矩阵

# 步长切片
print(A[:, 0::2])   # [[1, 3], [4, 6], [7, 9]]  每隔一列

# 布尔索引(条件筛选)
print(A[A > 5])     # [6, 7, 8, 9]    大于5的元素

# 花式索引(用数组索引)
print(A[[0, 2], [1, 2]])  # [2, 9]    (0,1) 和 (2,2) 位置的元素

形状操作

a = np.arange(12)

# 重塑
b = a.reshape(3, 4)         # 3行4列
c = a.reshape(3, -1)        # -1 表示自动推断: 3行4列
d = a.reshape(-1,)          # 展平为一维

# 转置与轴操作
M = np.random.randn(2, 3, 4)
print(M.shape)              # (2, 3, 4)
M_T = M.transpose(0, 2, 1) # 交换轴: (2, 4, 3)
M_swap = np.swapaxes(M, 1, 2)  # 同上

# 拼接
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
print(np.concatenate([a, b], axis=0))  # 沿行拼接: (4, 2)
print(np.concatenate([a, b], axis=1))  # 沿列拼接: (2, 4)
print(np.stack([a, b], axis=0))        # 堆叠: (2, 2, 2)

# 增加维度
v = np.array([1, 2, 3])
print(v.shape)              # (3,)
print(v[np.newaxis, :].shape)   # (1, 3)  等价于 v.reshape(1, -1)
print(v[:, np.newaxis].shape)   # (3, 1)  等价于 v.reshape(-1, 1)

广播(Broadcasting)

广播是 NumPy 中最强大的特性之一,它允许不同形状的数组进行运算。

# 规则:从末尾开始比较维度,满足以下条件之一即可广播:
# 1. 维度相等
# 2. 其中一个维度为 1

# 标量与数组运算
a = np.array([1, 2, 3])
print(a * 2)            # [2, 4, 6]  标量 2 被广播到每个元素

# 二维与一维运算
A = np.array([[1, 2, 3],
              [4, 5, 6]])    # (2, 3)
b = np.array([10, 20, 30])   # (3,)  → 广播为 (2, 3)
print(A + b)            # [[11, 22, 33], [14, 25, 36]]

# 列向量与行向量
col = np.array([[1], [2], [3]])  # (3, 1)
row = np.array([10, 20])         # (2,)  → 广播为 (1, 2)
print(col + row)        # (3, 2): [[11, 21], [12, 22], [13, 23]]

# 实际应用:对每行减去均值(数据归一化)
data = np.random.randn(5, 3)    # 5个样本,3个特征
mean = data.mean(axis=0)        # 每个特征的均值: (3,)
normalized = data - mean         # 广播: (5,3) - (3,) = (5,3)

深度学习框架:PyTorch

PyTorch 是当前最流行的深度学习框架之一,以其动态计算图和 Pythonic 的设计哲学著称。Transformer.md 中的所有代码都基于 PyTorch。

张量(Tensor)

张量是 PyTorch 的核心数据结构,本质上是多维数组,与 NumPy 的 ndarray 类似,但额外支持 GPU 加速和自动微分。

import torch

# === 创建张量 ===

# 从列表创建
t = torch.tensor([1, 2, 3, 4])             # 一维张量
m = torch.tensor([[1, 2], [3, 4]])          # 二维张量

# 常用创建函数
zeros = torch.zeros(3, 4)                   # 全零
ones = torch.ones(2, 3)                     # 全一
eye = torch.eye(4)                          # 单位矩阵
rand = torch.randn(3, 4)                    # 标准正态分布
rand_uniform = torch.rand(3, 4)             # [0, 1) 均匀分布
arange = torch.arange(0, 10, 2)             # [0, 2, 4, 6, 8]
linspace = torch.linspace(0, 1, 5)          # [0, 0.25, 0.5, 0.75, 1]
full = torch.full((3, 3), 3.14)             # 全部填充指定值

# 指定数据类型
t_float = torch.tensor([1, 2, 3], dtype=torch.float32)
t_int = torch.tensor([1, 2, 3], dtype=torch.int64)

# 张量属性
x = torch.randn(2, 3, 4)
print(x.shape)          # torch.Size([2, 3, 4])  形状
print(x.dtype)          # torch.float32           数据类型
print(x.device)         # cpu                     所在设备
print(x.dim())          # 3                       维度数
print(x.numel())        # 24                      元素总数

张量运算

a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([4.0, 5.0, 6.0])

# 逐元素运算
print(a + b)            # tensor([5., 7., 9.])
print(a - b)            # tensor([-3., -3., -3.])
print(a * b)            # tensor([ 4., 10., 18.])  逐元素乘法
print(a / b)            # tensor([0.2500, 0.4000, 0.5000])
print(a ** 2)           # tensor([1., 4., 9.])

# 聚合运算
print(a.sum())          # tensor(6.)
print(a.mean())         # tensor(2.)
print(a.max())          # tensor(3.)
print(a.min())          # tensor(1.)
print(a.argmax())       # tensor(2)  最大值索引

# 矩阵运算
A = torch.randn(2, 3)
B = torch.randn(3, 4)

# 矩阵乘法(三种等价写法)
C1 = A @ B              # (2, 4)  推荐写法
C2 = torch.matmul(A, B) # (2, 4)
C3 = torch.mm(A, B)     # (2, 4)  仅限二维

# 转置
print(A.T)              # (3, 2)
print(A.transpose(0, 1)) # 等价写法,指定交换的维度

# 批量矩阵乘法(Transformer 中最常见的操作)
# 用于并行计算多个样本的注意力分数
batch_A = torch.randn(8, 3, 4)     # 8个 3×4 矩阵
batch_B = torch.randn(8, 4, 5)     # 8个 4×5 矩阵
batch_C = batch_A @ batch_B         # (8, 3, 5)  逐个矩阵相乘
# 或者
batch_C = torch.bmm(batch_A, batch_B)  # 等价

# 点积(向量内积)
v1 = torch.tensor([1.0, 2.0, 3.0])
v2 = torch.tensor([4.0, 5.0, 6.0])
print(torch.dot(v1, v2))  # tensor(32.) = 1*4 + 2*5 + 3*6

形状操作

PyTorch 的形状操作与 NumPy 非常相似,但有些方法名不同。

x = torch.arange(24).float()

# reshape / view:改变形状
a = x.reshape(2, 3, 4)         # (2, 3, 4)
b = x.view(2, 3, 4)            # 同上(view 要求内存连续)
c = x.reshape(2, -1)           # (2, 12)  -1 自动推断

# view 与 reshape 的区别:
# view 共享内存,要求张量在内存中连续;reshape 可能创建副本
# 在 Transformer 代码中,通常先 .contiguous() 再 .view()

# 转置与维度交换
M = torch.randn(2, 3, 4)
M_T = M.transpose(1, 2)        # 交换维度1和2: (2, 4, 3)
M_perm = M.permute(0, 2, 1)    # 更通用的维度重排: (2, 4, 3)

# contiguous:使张量在内存中连续
# transpose/permute 后的张量在内存中不连续,需要 contiguous() 才能 view
M_cont = M_T.contiguous()      # 确保内存连续

# 拼接
a = torch.randn(2, 3)
b = torch.randn(2, 3)
cat_0 = torch.cat([a, b], dim=0)    # (4, 3)  沿维度0拼接
cat_1 = torch.cat([a, b], dim=1)    # (2, 6)  沿维度1拼接
stack = torch.stack([a, b], dim=0)  # (2, 2, 3)  堆叠(增加新维度)

# 增加/减少维度
v = torch.tensor([1.0, 2.0, 3.0])
print(v.shape)                      # torch.Size([3])
v_unsq = v.unsqueeze(0)             # (1, 3)  等价于 v[None, :]
v_unsq2 = v.unsqueeze(1)            # (3, 1)  等价于 v[:, None]
s = torch.tensor([[1.0, 2.0, 3.0]])
s_sq = s.squeeze(0)                 # (3,)  去掉大小为1的维度

索引与切片

x = torch.arange(24).reshape(2, 3, 4).float()
# 形状 (2, 3, 4)

# 基本索引
print(x[0])             # 第0个: (3, 4)
print(x[0, 1])          # 第0个的第1行: (4,)
print(x[0, 1, 2])       # 标量: tensor(6.)

# 切片(与 NumPy 相同)
print(x[:, 0:2, :])     # 所有样本,前2行: (2, 2, 4)
print(x[0, :, 0::2])    # 第0个样本,所有行,每隔一列: (3, 2)

# 布尔索引
mask = x > 12
print(x[mask])          # 一维张量,包含所有大于12的元素

# 花式索引
indices = torch.tensor([0, 2])
print(x[0, indices])    # 第0个样本的第0行和第2行: (2, 4)

掩码操作

掩码操作在 Transformer 的注意力机制中至关重要。

# 创建掩码张量
scores = torch.randn(3, 3)

# 下三角掩码(因果掩码,用于解码器)
causal_mask = torch.tril(torch.ones(3, 3))
print(causal_mask)
# tensor([[1., 0., 0.],
#         [1., 1., 0.],
#         [1., 1., 1.]])

# masked_fill:将掩码为0的位置填充为指定值
scores_masked = scores.masked_fill(causal_mask == 0, float('-inf'))
# 掩码为 0 的位置被替换为 -inf,softmax 后变为 0

# 上三角掩码
upper_mask = torch.triu(torch.ones(3, 3), diagonal=1)
print(upper_mask)
# tensor([[0., 1., 1.],
#         [0., 0., 1.],
#         [0., 0., 0.]])

# 应用 softmax 后,-inf 位置变为 0
weights = torch.softmax(scores_masked, dim=-1)
print(weights)
# 每一行是一个概率分布,对角线以下(含对角线)有值,其余为0

设备管理(CPU / GPU)

# 检查 GPU 是否可用
print(torch.cuda.is_available())    # True / False

# 将张量移到 GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
x = torch.randn(3, 4)
x = x.to(device)                    # 移到 GPU(如果可用)

# 创建时直接指定设备
x_gpu = torch.randn(3, 4, device='cuda')

# 移回 CPU
x_cpu = x.cpu()

# 模型移到 GPU
# model = model.to(device)

# 获取张量值(从 GPU 移到 CPU 并转为 Python 数字)
val = x[0, 0].item()                # 仅适用于标量张量
arr = x.detach().cpu().numpy()      # 转为 NumPy 数组

自动微分(Autograd)

自动微分是深度学习的核心——它自动计算梯度,使得反向传播成为可能。

import torch

# requires_grad=True 告诉 PyTorch 需要追踪这个张量上的操作
x = torch.tensor([2.0, 3.0], requires_grad=True)

# 前向计算
y = x ** 2 + 3 * x + 1
z = y.sum()         # 标量才能调用 .backward()

# 反向传播:计算 dz/dx
z.backward()

# 梯度:dz/dx = 2x + 3
print(x.grad)       # tensor([7., 9.])  即 [2*2+3, 2*3+3]

计算图与反向传播

PyTorch 使用动态计算图——每次前向传播时实时构建计算图,反向传播后自动释放。这使得调试和控制流(如 if、for)非常自然。

# 在 Transformer 中的实际使用
model = SomeModel()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

# 训练循环
for epoch in range(num_epochs):
    # 前向传播
    logits = model(src, tgt)            # 自动构建计算图
    loss = F.cross_entropy(logits, target)

    # 反向传播
    optimizer.zero_grad()               # 清除旧梯度
    loss.backward()                     # 计算梯度,填充 .grad
    optimizer.step()                    # 更新参数

torch.nn 模块

torch.nn 是 PyTorch 的神经网络模块,提供了构建网络所需的所有组件。

import torch
import torch.nn as nn
import torch.nn.functional as F

nn.Module:所有网络的基类

class MyModel(nn.Module):
    def __init__(self):
        super().__init__()                  # 必须调用父类构造函数
        self.linear = nn.Linear(10, 5)      # 线性层
        self.relu = nn.ReLU()               # 激活函数

    def forward(self, x):                   # 定义前向传播
        x = self.linear(x)
        x = self.relu(x)
        return x

model = MyModel()
print(model)            # 打印网络结构
print(list(model.parameters()))  # 列出所有可学习参数

常用层

# 线性层(全连接层): y = xW^T + b
linear = nn.Linear(in_features=512, out_features=2048, bias=True)
x = torch.randn(1, 10, 512)     # (batch, seq_len, d_model)
y = linear(x)                    # (1, 10, 2048)
print(y.shape)

# 无偏置的线性层(Transformer 中常用)
linear_no_bias = nn.Linear(512, 512, bias=False)

# 嵌入层:将整数索引映射为向量
embedding = nn.Embedding(num_embeddings=10000, embedding_dim=512)
token_ids = torch.tensor([[1, 5, 42, 7]])   # token ID
embedded = embedding(token_ids)              # (1, 4, 512)
print(embedded.shape)

# 参数
print(embedding.weight.shape)   # (10000, 512)  可学习的嵌入表

# nn.Parameter:将普通张量注册为模型参数
class MyLayer(nn.Module):
    def __init__(self, d_model):
        super().__init__()
        # 这两个参数会被 model.parameters() 自动追踪
        self.gamma = nn.Parameter(torch.ones(d_model))
        self.beta = nn.Parameter(torch.zeros(d_model))

# register_buffer:注册不参与梯度计算的"缓冲区"
class MyTransformer(nn.Module):
    def __init__(self):
        super().__init__()
        # 位置编码是预计算的,不需要梯度
        pe = torch.zeros(100, 512)
        self.register_buffer('pos_encoding', pe)

# nn.ModuleList:管理子模块列表
class MyEncoder(nn.Module):
    def __init__(self, num_layers=6):
        super().__init__()
        # ModuleList 中的模块会被正确注册
        self.layers = nn.ModuleList([
            nn.Linear(512, 512) for _ in range(num_layers)
        ])

    def forward(self, x):
        for layer in self.layers:
            x = layer(x)
        return x

激活函数

# ReLU: max(0, x)
relu = nn.ReLU()
x = torch.tensor([-2.0, -1.0, 0.0, 1.0, 2.0])
print(relu(x))          # tensor([0., 0., 0., 1., 2.])

# 也可以用函数式接口
print(F.relu(x))        # 同上

# GELU(现代 Transformer 中更常用)
gelu = nn.GELU()
print(gelu(x))          # tensor([-0.0455, -0.1588,  0.0000,  0.8412, 1.9545])

# Sigmoid: 1 / (1 + exp(-x))
sigmoid = nn.Sigmoid()
print(sigmoid(x))       # tensor([0.1192, 0.2689, 0.5000, 0.7311, 0.8808])

# Softmax: 将向量转换为概率分布
softmax = nn.Softmax(dim=-1)
logits = torch.tensor([2.0, 1.0, 0.1])
print(softmax(logits))  # tensor([0.6590, 0.2424, 0.0986])
# 注意: softmax 在 Transformer.md 中用 torch.softmax(scores, dim=-1) 调用

损失函数

# 交叉熵损失(分类任务最常用)
# 内部包含 Softmax,所以输入应该是 logits,不是概率
criterion = nn.CrossEntropyLoss()

logits = torch.randn(3, 5)     # 3个样本,5个类别
targets = torch.tensor([0, 2, 4])  # 真实类别
loss = criterion(logits, targets)
print(loss)                    # tensor(1.6094)

# 函数式接口
loss = F.cross_entropy(logits, targets)

# 对于 Transformer 的输出
# logits: (batch, seq_len, vocab_size)
# targets: (batch, seq_len)
# 需要 reshape
logits_flat = logits.view(-1, 5)     # (3, 5)
targets_flat = targets.view(-1)      # (3,)
loss = F.cross_entropy(logits_flat, targets_flat)

优化器

import torch.optim as optim

model = MyModel()

# Adam 优化器(最常用)
optimizer = optim.Adam(model.parameters(), lr=1e-3)

# 带权重衰减(L2 正则化)
optimizer = optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-5)

# AdamW(现代 Transformer 训练推荐)
optimizer = optim.AdamW(model.parameters(), lr=1e-3, weight_decay=0.01)

# 学习率调度器
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
# 每 10 个 epoch,学习率乘以 0.1

scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=100)
# 余弦退火:学习率按余弦曲线衰减

完整训练循环

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

# 1. 定义模型
class SimpleNet(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super().__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.fc2 = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 2. 准备数据
X_train = torch.randn(100, 10)          # 100 个样本,10 维特征
y_train = torch.randint(0, 3, (100,))   # 100 个标签(0, 1, 2)

# 3. 创建模型和优化器
model = SimpleNet(10, 32, 3)
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 4. 训练循环
for epoch in range(100):
    # 前向传播
    logits = model(X_train)
    loss = F.cross_entropy(logits, y_train)

    # 反向传播
    optimizer.zero_grad()   # 清除旧梯度(PyTorch 默认累加梯度)
    loss.backward()         # 计算梯度
    optimizer.step()        # 更新参数

    if (epoch + 1) % 20 == 0:
        acc = (logits.argmax(dim=1) == y_train).float().mean()
        print(f"Epoch {epoch+1}, Loss: {loss.item():.4f}, Acc: {acc.item():.4f}")

# 5. 推理
with torch.no_grad():       # 不追踪梯度,节省内存
    test_x = torch.randn(5, 10)
    pred = model(test_x).argmax(dim=1)
    print(f"预测: {pred}")

完整的 Transformer 训练示例

结合以上所有知识,下面是 Transformer.md 中代码的完整训练流程:

import torch
import torch.nn as nn
import torch.nn.functional as F
import math

# (此处包含 Transformer.md 中定义的所有组件)
# MultiHeadAttention, LayerNorm, FeedForward, EncoderBlock, DecoderBlock, TinyTransformer

# 准备数据
src_vocab_size = 50
tgt_vocab_size = 50
model = TinyTransformer(src_vocab_size, tgt_vocab_size,
                        d_model=16, num_heads=4, d_ff=64, num_layers=2)

# 模拟训练数据
src_ids = torch.tensor([[3, 7, 12, 5, 9]])   # 源序列
tgt_ids = torch.tensor([[2, 15, 8, 4]])       # 目标序列(输入)
target = torch.tensor([[5, 12, 3, 8]])         # 目标序列(标签,偏移一位)

# 优化器
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

# 训练一步
logits = model(src_ids, tgt_ids)                # (1, 4, 50)
loss = F.cross_entropy(logits.view(-1, 50), target.view(-1))

optimizer.zero_grad()                           # 清除旧梯度
loss.backward()                                 # 反向传播
optimizer.step()                                # 更新参数

print(f"Loss: {loss.item():.4f}")

数据处理与可视化

Matplotlib:绑图可视化

import matplotlib.pyplot as plt
import numpy as np

# 基本折线图
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)

plt.figure(figsize=(10, 6))
plt.plot(x, y, label='sin(x)', color='blue', linewidth=2)
plt.plot(x, np.cos(x), label='cos(x)', color='red', linewidth=2, linestyle='--')
plt.xlabel('x')
plt.ylabel('y')
plt.title('三角函数')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('trig.png', dpi=150, bbox_inches='tight')
plt.show()

# 子图
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

axes[0, 0].plot(x, np.sin(x))
axes[0, 0].set_title('sin(x)')

axes[0, 1].plot(x, np.cos(x))
axes[0, 1].set_title('cos(x)')

axes[1, 0].bar([1, 2, 3], [3, 1, 4])
axes[1, 0].set_title('柱状图')

axes[1, 1].scatter(np.random.randn(50), np.random.randn(50))
axes[1, 1].set_title('散点图')

plt.tight_layout()
plt.show()

# 训练曲线可视化
def plot_training(train_losses, val_losses, train_accs, val_accs):
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

    ax1.plot(train_losses, label='Train Loss')
    ax1.plot(val_losses, label='Val Loss')
    ax1.set_xlabel('Epoch')
    ax1.set_ylabel('Loss')
    ax1.set_title('Loss Curve')
    ax1.legend()

    ax2.plot(train_accs, label='Train Acc')
    ax2.plot(val_accs, label='Val Acc')
    ax2.set_xlabel('Epoch')
    ax2.set_ylabel('Accuracy')
    ax2.set_title('Accuracy Curve')
    ax2.legend()

    plt.tight_layout()
    plt.show()

Pandas:数据分析

import pandas as pd

# 创建 DataFrame
data = {
    'name': ['疾旋鼬', '捣蛋猫', '桃旋鼬', '火绒狐'],
    'type': ['龙', '无', '龙', '火'],
    'hp': [120, 80, 100, 90],
    'attack': [85, 60, 75, 95],
}
df = pd.DataFrame(data)

# 查看数据
print(df.head())                # 前5行
print(df.describe())            # 统计摘要
print(df.info())                # 数据类型信息

# 筛选
dragon = df[df['type'] == '龙']        # 筛选龙属性
strong = df[df['attack'] > 80]         # 筛选攻击>80

# 排序
sorted_df = df.sort_values('hp', ascending=False)

# 添加列
df['total'] = df['hp'] + df['attack']

# 分组统计
type_stats = df.groupby('type').mean(numeric_only=True)

# 读取/保存文件
# df = pd.read_csv('data.csv')
# df.to_csv('output.csv', index=False)

常用标准库与工具

os 与 pathlib:文件系统操作

import os
from pathlib import Path

# 获取当前工作目录
cwd = os.getcwd()

# 路径拼接
config_path = os.path.join(cwd, 'config', 'model.yaml')

# 使用 pathlib(更现代的方式)
p = Path('.')
config = p / 'config' / 'model.yaml'
print(config.exists())       # True / False
print(config.suffix)         # '.yaml'
print(config.parent)         # config/

# 列出目录下的文件
for f in Path('.').glob('*.py'):
    print(f)

# 递归搜索
for f in Path('.').rglob('*.md'):
    print(f)

collections:高级数据结构

from collections import defaultdict, Counter, OrderedDict

# defaultdict:带默认值的字典
word_count = defaultdict(int)       # 默认值为 0
for word in ['疾旋鼬', '捣蛋猫', '疾旋鼬', '桃旋鼬', '疾旋鼬']:
    word_count[word] += 1
print(dict(word_count))  # {'疾旋鼬': 3, '捣蛋猫': 1, '桃旋鼬': 1}

# Counter:计数器
words = ['疾旋鼬', '捣蛋猫', '疾旋鼬', '桃旋鼬', '疾旋鼬']
counter = Counter(words)
print(counter)                    # Counter({'疾旋鼬': 3, '捣蛋猫': 1, '桃旋鼬': 1})
print(counter.most_common(2))     # [('疾旋鼬', 3), ('捣蛋猫', 1)]

typing:类型注解

类型注解不影响运行时行为,但能让代码更易读,并被 IDE 和工具用于静态检查。

from typing import Optional, List, Tuple, Dict

def attention(
    Q: torch.Tensor,        # (batch, seq, d_model)
    K: torch.Tensor,        # (batch, seq, d_model)
    V: torch.Tensor,        # (batch, seq, d_model)
    mask: Optional[torch.Tensor] = None,  # 可选参数
) -> Tuple[torch.Tensor, torch.Tensor]:
    """返回 (注意力输出, 注意力权重)"""
    d_k = Q.size(-1)
    scores = Q @ K.transpose(-2, -1) / (d_k ** 0.5)
    if mask is not None:
        scores = scores.masked_fill(mask == 0, float('-inf'))
    weights = torch.softmax(scores, dim=-1)
    return weights @ V, weights

# Python 3.10+ 更简洁的写法
def process(data: list[str]) -> dict[str, float]:
    ...

functools:函数工具

from functools import partial, lru_cache

# partial:创建偏函数(固定部分参数)
# 在 Transformer 中,常用 partial 来简化优化器的创建
from torch.optim import Adam
create_optimizer = partial(Adam, lr=1e-3, betas=(0.9, 0.98))
optimizer = create_optimizer(model.parameters())

# lru_cache:缓存函数结果(适用于纯函数)
@lru_cache(maxsize=128)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(100))  # 354224848179261915075(瞬间完成)

time 与 tqdm:计时与进度条

import time
from tqdm import tqdm

# 计时
start = time.time()
# ... 一些计算 ...
elapsed = time.time() - start
print(f"耗时: {elapsed:.2f}s")

# tqdm 进度条(训练循环中常用)
for epoch in tqdm(range(100), desc="Training"):
    # 训练逻辑
    time.sleep(0.01)  # 模拟训练

random:随机数

import random

# 设置随机种子(确保可复现性)
random.seed(42)
torch.manual_seed(42)
np.random.seed(42)
if torch.cuda.is_available():
    torch.cuda.manual_seed_all(42)

# 常用操作
print(random.random())            # [0, 1) 随机浮点数
print(random.randint(1, 100))     # [1, 100] 随机整数
print(random.choice([1, 2, 3]))   # 随机选择一个
print(random.sample(range(100), 5))  # 无放回抽样5个

re:正则表达式

import re

text = "疾旋鼬的HP是120,桃旋鼬的HP是90"

# 查找数字
numbers = re.findall(r'\d+', text)
print(numbers)          # ['120', '90']

# 匹配模式
pattern = r'(\w+)的HP是(\d+)'
matches = re.findall(pattern, text)
print(matches)          # [('疾旋鼬', '120'), ('桃旋鼬', '90')]

# 替换
cleaned = re.sub(r'\d+', '***', text)
print(cleaned)          # 疾旋鼬的HP是***,桃旋鼬的HP是***

附录:Python 语法速查表

语法 说明 示例
f"{x:.2f}" 格式化字符串 f"{3.14159:.2f}" → "3.14"
*args 可变位置参数 def f(*args): print(args)
**kwargs 可变关键字参数 def f(**kwargs): print(kwargs)
[x for x in it] 列表推导式 [x**2 for x in range(5)]
{k: v for k, v in it} 字典推导式 {x: x**2 for x in range(5)}
{x for x in it} 集合推导式 {x % 3 for x in range(10)}
a, b = b, a 交换变量 利用元组解包
x if cond else y 三元表达式 a if a > 0 else 0
lambda x: expr 匿名函数 lambda x: x + 1
with open(...) as f: 上下文管理器 自动关闭文件
try/except/finally 异常处理 捕获并处理错误
@property 属性装饰器 像属性一样调用方法
@staticmethod 静态方法 不需要实例和 self
@classmethod 类方法 接收类本身作为 cls
x @ y 矩阵乘法 PyTorch/NumPy 均支持
x.T 转置 行列互换
x.shape 形状 (batch, seq, dim)
x.view(...) 重塑 改变形状,共享内存
x.reshape(...) 重塑 改变形状,可能复制
x.unsqueeze(dim) 增加维度 (3,) → (1, 3)
x.squeeze(dim) 减少维度 (1, 3) → (3,)
x.item() 转为 Python 数字 仅限标量张量
x.detach() 从计算图分离 停止梯度追踪

我们也有一些关于安全的Python实用说明,您可以参见Python for Security。

今天让我emo的人问我怎么又emo了……嗯嘟……

2026.05.11