0、Jupyter Notebook 是什么
0.1 .ipynb 文件
.ipynb 是 Jupyter Notebook 的文件格式,全称 iPython Notebook。它是一个 JSON 结构的文件,将代码、运行输出、Markdown 文档混排在一起,类似于一个可以运行的笔记本。
一个 .ipynb 文件 = 多个 Cell(单元格)的组合:
- Code Cell:可执行的代码块,运行后下方直接显示输出
- Markdown Cell:写文档笔记用的
0.2 本次使用的平台:ModeScope(魔搭社区)
notebook 注释中提到 # modescope 内置了openai,这里用的是**阿里云天池/魔搭社区(ModeScope)**的在线 Notebook 环境。它的特点是:
- 浏览器内直接运行 Python,无需本地安装
- 预装了 openai、pandas 等常用库
- 适合学习、数据分析、AI 模型调用
0.3 Hello World
print("My first NoteBook")
# 输出:My first NoteBook
一切从这里开始——在 Notebook 中运行第一行 Python 代码。
一、Python 列表(List)与数组
1.1 核心认知:Python 没有 Java/C++ 那种内置数组
notebook 原文注释写道:
在Python里面,本身没有Java/C++那种内置数组
Python 里的 list,不等于 Java/C++ 里的 array。必须把这个概念先搞清楚。
1.2 三方面对比
| 维度 | Python list | Java 数组 | C++ 数组 | JavaScript 数组 |
|---|---|---|---|---|
| 长度 | 动态可变,无需预设容量 | 固定,声明时必须指定 | 编译期确定 | 动态,自动扩容 |
| 元素类型 | 不约束,可混合 int/str/object | 严格限定声明类型 | 严格限定类型 | 不约束 |
| 底层 | 动态数组(类似 Java ArrayList) | 静态连续内存 | 静态连续内存 | 动态数组 |
结论:Python 的 list 更像 JS 的数组 或 Java 的 ArrayList——动态、灵活、异构。
notebook 注释验证:
"长度是否可变,list和js的数组是动态的,无需指定容量" "在list里面不约束值的类型"
1.3 基本操作
L = ["Niko", "Monesy", "Teses", "kyousuky", "karrigen"]
# 直接用索引拿到前三项(硬编码方式)
[L[0], L[1], L[2]] # ['Niko', 'Monesy', 'Teses']
# "人生苦短,我用python" —— 开始写循环
r = []
n = 3
for i in range(n): # range(n) → 0, 1, ..., n-1
r.append(L[i]) # append() 往列表末尾追加元素
r # ['Niko', 'Monesy', 'Teses']
此处的知识点:
range(n):生成从 0 到 n-1 的整数序列,左闭右开。range(3)依次产出0, 1, 2,等价于[0, 3)这个数学区间。list.append(item):往列表末尾追加元素,列表长度自动 +1,体现了动态数组的特性。- "人生苦短,我用python":这是 Python 社区的一句经典 slogan(Life is short, you need Python),这里用它调侃——"别的语言写个循环这么啰嗦,用 Python 轻松搞定",而后面学了切片之后会更简洁。
二、切片(Slice)—— 取代手动循环
切片是 Python 区别于其他语言的一个标志性特性。
2.1 基本切片
L[0:3] # ['Niko', 'Monesy', 'Teses'] 索引 0,1,2(不包含 3)
L[:3] # 同上,省略 start 默认从 0 开始
L[1:3] # ['Monesy', 'Teses'] 索引 1,2(不包含 3)
L[-2:] # ['kyousuky', 'karrigen'] 倒数两个
核心规则:L[start:stop] — 左闭右开 [start, stop),和 range() 保持一致性。
2.2 带步长的切片
L = list(range(100)) # [0, 1, 2, ..., 99]
L[:5] # [0, 1, 2, 3, 4] 前 5 个
L[-5:] # [95, 96, 97, 98, 99] 后 5 个
L[:10:2] # [0, 2, 4, 6, 8] 前 10 个中隔一个取一个
L[::5] # [0, 5, 10, ..., 95] 整个列表每隔 5 个取一个
2.3 字符串切片
切片不是 list 专属,str、tuple 等一切序列类型都支持:
'ABCDEFG'[:3] # 'ABC'
'ABCDEFG'[::2] # 'ACEG'
2.4 切片语法总结
| 写法 | 含义 |
|---|---|
seq[:3] | 取前三项 |
seq[1:3] | 取索引 1,2(不含 3) |
seq[-2:] | 取后两项 |
seq[::2] | 从头到尾,步长 2(跳一个取一个) |
seq[::-1] | 反转序列 |
对比:之前用 for + range + append 取前三项(5 行代码),现在一行 L[:3] 搞定。
三、字符串处理:手工实现 strip/trim
3.1 调用内置方法
def trim(s):
return s.strip()
print(trim(" hello world ")) # "hello world"
str.strip() 去掉首尾空白(空格、制表符、换行符等),类似的还有 lstrip()(只去左边)和 rstrip()(只去右边)。
3.2 不用 API,手写实现(双指针法)
def trim(s):
left = 0
while left < len(s) and s[left] == ' ':
left += 1 # 找到第一个非空格字符的位置
right = len(s) # 从末尾开始(注意:赋的是长度,不是索引)
while right > left and s[right - 1] == ' ':
right -= 1 # 找到最后一个非空格字符的后一个位置
return s[left:right] # 切片左闭右开,正好截取中间非空部分
为什么 right = len(s) 而不是 len(s) - 1?
注释写得很清楚:# 因为切片右是开区间。切片是左闭右开 [left, right),所以 right 指向的是"最后一个有效字符的下一个位置"。如果 right = len(s) - 1,切片会少取最后一个字符。
算法本质:双指针(two-pointer)—— left 从左边逼近,right 从右边逼近,最后的 s[left:right] 就是 trim 结果。这也是 LeetCode 和面试中的高频模式。
四、模块化与 API 调用
4.1 模块化导入——Python vs JavaScript
notebook 注释特意做了对比:
# 在js里面是 import OpenAi from openai
# 这是模块化的体现,引入第三方模块
Python 的 import vs JS 的 import:
| 语言 | 导入语法 | 本质 |
|---|---|---|
| Python | from openai import OpenAI | 从 openai 包中引入 OpenAI 这个类 |
| JavaScript (ES6) | import OpenAI from 'openai' | 从 npm 包中引入默认导出 |
虽然语法不同,但模块化的思想完全一致:将功能封装在独立的包/模块中,按需引入。
4.2 Python 实例化——不需要 new
# python不用new,直接调用构造函数运行实例化
client = OpenAI(
api_key="sk-d3948ce218714344b96211cfef686757",
base_url="https://api.deepseek.com/v1"
)
对比:
| 语言 | 创建对象 |
|---|---|
| Python | client = OpenAI(...) 直接调用类名 |
| JavaScript | const client = new OpenAI(...) 需要 new |
| Java / C++ | 必须 new ClassName(...) |
Python 把类名直接当作"工厂函数"来用,OpenAI(...) 等价于调用 __init__ 构造方法。
4.3 完整调用代码
from openai import OpenAI
client = OpenAI(
api_key="sk-xxxx",
base_url="https://api.deepseek.com/v1" # 指向 DeepSeek,而非 OpenAI 官方
)
COMPLETION_MODEL = "deepseek-chat"
prompt = """
Consideration product: 工厂现货PVC充气青蛙夜市地摊热卖充气玩具发光蛙儿童水上玩具
1. Compose human readable product title used on Amazon in english within 20 words.
2. Write 5 selling points for the products in Amazon.
3. Evaluate a price range for this product in U.S.
Output the result in json format with three properties called title, selling_point and price_range
"""
def get_response(prompt):
response = client.chat.completions.create(
model=COMPLETION_MODEL,
messages=[
{"role": "user", "content": prompt}
]
)
return response.choices[0].message.content
两个关键参数
- model:指定用哪个模型,如“deepseek-chat”、“gpt-4”
- messages:对话历史,是一个列表,每条消息包含role(角色)和content(内容)
4.4 调用链拆解
client.chat.completions.create(model=..., messages=...)
│
▼
response 对象
│
▼
response.choices # 一个列表,存放所有候选回复
│
▼
response.choices[0] # 取第一个候选(通常只有 1 个)
│
▼
.message.content # 拿到模型回复的文本内容
关键设计:
base_url="https://api.deepseek.com/v1"—— DeepSeek 的 API 兼容 OpenAI 格式,只需改这一行 URL 就能切换模型提供商,无需重写调用代码。messages = [{"role":"user", "content": prompt}]—— 对话消息以列表形式传入,role可以是"user"(用户)、"assistant"(助手)、"system"(系统指令)。
4.5 Prompt 工程要点
这个 prompt 包含了三个要素:
- 清晰且详细的表达目标:
Consideration product: 工厂现货PVC充气青蛙... - 分步骤:把复杂的要求设计分出几个步骤,LLM更好理解
- 约束下LLM返回内容的格式:JSON,指定三个属性名
title、selling_points、price_range
五、知识图谱
┌─────────────────────────────────────────────────┐
│ Python 基础 │
├─────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ 列表list │ │切片slice │ │ 字符串str │ |
│ │ │ │ │ │ │ │
│ │· 动态长度 │ │· [:] │ │· strip() │ │
│ │· 异构存储 │ │· [::] │ │· 双指针trim │ │
│ │· append() │ │· 左闭右开 │ │· 切片适用str │ │
│ └────┬─────┘ └────┬─────┘ └──────┬───────┘ │
│ │ │ │ │
│ └──────────────┼────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────┐ │
│ │ 序列通用操作 │ │
│ │ list/str/tuple │ │
│ │ 都支持切片和索引 │ │
│ └───────────────────┘ │
│ │
├─────────────────────────────────────────────────┤
│ 工程实践 │
├─────────────────────────────────────────────────┤
│ │
│ ┌────────────┐ ┌────────────┐ ┌──────────┐ │
│ │ 模块化import│ │ API 调用 │ │ Prompt │ │
│ │ │ │ │ │ 工程 │ │
│ │· from x │ │· OpenAI SDK│ │· 任务描述 │ │
│ │ import y │ │· DeepSeek │ │· 格式约束 │ │
│ │· 对比JS │ │· 兼容URL │ │· JSON输出 │ │
│ └────────────┘ └────────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────┘
六、代码速查卡
列表
L = ["a", "b", "c", "d", "e"]
L[0] # 第一个
L[-1] # 最后一个
L.append(1) # 追加
len(L) # 长度
list(range(5))# [0,1,2,3,4]
切片
L[:3] # 前三
L[-2:] # 后二
L[1:4] # 索引 1,2,3
L[::2] # 隔一取一
L[::-1] # 反转
字符串
s.strip() # 去首尾空格
s[left:right] # 切片截取
API 调用
from openai import OpenAI
client = OpenAI(api_key="...", base_url="...")
r = client.chat.completions.create(model="...", messages=[...])
r.choices[0].message.content
重点:prompt设计的三要素:1、清晰详细的表达 2、分步骤 3、约束下llm返回内容的格式