Python 基础与 API 实践

14 阅读7分钟

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 listJava 数组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']

此处的知识点

  1. range(n):生成从 0 到 n-1 的整数序列,左闭右开。range(3) 依次产出 0, 1, 2,等价于 [0, 3) 这个数学区间。
  2. list.append(item):往列表末尾追加元素,列表长度自动 +1,体现了动态数组的特性。
  3. "人生苦短,我用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

语言导入语法本质
Pythonfrom 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"
)

对比:

语言创建对象
Pythonclient = OpenAI(...) 直接调用类名
JavaScriptconst 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 包含了三个要素:

  1. 清晰且详细的表达目标Consideration product: 工厂现货PVC充气青蛙...
  2. 分步骤:把复杂的要求设计分出几个步骤,LLM更好理解
  3. 约束下LLM返回内容的格式:JSON,指定三个属性名 titleselling_pointsprice_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返回内容的格式