知识点思维导图
29 个知识节点
参考资料
Python(37) - A3 - 附录-JS到Python速查表
写代码时卡在「这个 JS 操作 Python 怎么写」?本篇就是给你随时翻的双向对照表。不讲原理(原理在各专题篇),只回答一个问题:我会的 JS 写法,等价的 Python 是什么,以及哪里会咬人。
一、怎么用本篇
- 正向查(JS → Python):知道 JS 怎么写,想要 Python 等价写法 → 看每张表左列找右列。
- 反向查(Python → JS):读别人 Python 代码看不懂某个写法 → 用表格右列反查左列。
- 表格里凡是标了 ⚠️ 的,都是长得像但行为不一样的坑,看到必须停一下。
- 想深入某个点,跟着「详见第 X 篇」的索引去对应专题篇。
心智模型一句话:Python ≈ 不写类型的 JS + 用缩进代替
{}+ 用换行代替;。上手比 Java 顺,真正的坑集中在「几个同名不同义的关键字」和「self/ 可变默认参数」这几个点上。
二、变量与基本类型
2.1 变量声明
| JavaScript / TypeScript | Python |
|---|---|
let name = "Tom" |
name = "Tom" |
const AGE = 18 |
AGE = 18(全大写=约定常量,⚠️ 语言层面照样能改) |
let a = b = 0 |
a = b = 0(多变量同值) |
let [a, b] = [1, 2] |
a, b = 1, 2(解构,不用方括号) |
let [a, ...rest] = arr |
a, *rest = arr(* 收尾) |
⚠️ 三个最容易写错的常量:JS 的 true / false / null 在 Python 里是 True / False / None(首字母大写),写小写直接 NameError。
2.2 基本类型对照
| JS/TS | Python | 说明 |
|---|---|---|
number |
int / float |
⚠️ Python 整数和浮点是两种类型,10 是 int,10.0 是 float |
string |
str |
单双引号都行 |
boolean |
bool |
True / False |
null / undefined |
None |
⚠️ 只有一个 None,没有 undefined |
Array |
list |
[1, 2, 3] |
object / Map |
dict |
{"k": "v"} |
Set |
set |
{1, 2, 3} |
[a, b](只读) |
tuple |
(1, 2),不可变 |
2.3 类型转换
// JavaScript
Number("42"); // 字符串转数字
String(42); // 数字转字符串
parseInt("42px"); // 容错解析 → 42
三、字符串操作
| JavaScript | Python | 说明 |
|---|---|---|
`Hi ${name}` |
f"Hi {name}" |
模板字符串 → f-string(详见 1.x) |
str.length |
len(str) |
⚠️ 不是属性,是内置函数 len() |
str.toUpperCase() |
str.upper() |
转大写 |
str.toLowerCase() |
str.lower() |
转小写 |
str.trim() |
str.strip() |
去首尾空白 |
str.includes("x") |
"x" in str |
⚠️ 用 in 运算符,不是方法 |
str.indexOf("x") |
str.find("x") |
找不到时 find 返回 -1 |
str.split(",") |
str.split(",") |
一样 |
arr.join(",") |
",".join(arr) |
⚠️ 主客颠倒:分隔符在前调用 |
str.replace(a, b) |
str.replace(a, b) |
⚠️ Python 默认替换全部,JS 默认只换第一个 |
str.startsWith("x") |
str.startswith("x") |
注意全小写 |
str.slice(1, 3) |
str[1:3] |
切片,详见第六节 |
str.repeat(3) |
str * 3 |
⚠️ 直接用 * 乘 |
// JavaScript:模板字符串
const name = "Tom", age = 18;
const msg = `${name} is ${age}, next year ${age + 1}`;
四、数组 / 列表(list)
4.1 增删改查
| JavaScript | Python | 说明 |
|---|---|---|
arr.push(x) |
arr.append(x) |
尾部追加 |
arr.pop() |
arr.pop() |
弹出末尾 |
arr.shift() |
arr.pop(0) |
弹出头部 |
arr.unshift(x) |
arr.insert(0, x) |
头部插入 |
arr.length |
len(arr) |
⚠️ 用 len() |
arr.includes(x) |
x in arr |
⚠️ 用 in |
arr.indexOf(x) |
arr.index(x) |
⚠️ 找不到 Python 会抛异常,不是返回 -1 |
arr.concat(b) |
arr + b |
直接相加拼接 |
arr.reverse() |
arr.reverse() |
原地反转 |
[...arr] |
arr.copy() 或 arr[:] |
浅拷贝 |
arr.slice(1, 3) |
arr[1:3] |
切片 |
4.2 遍历
// JavaScript
for (const item of arr) { ... }
arr.forEach((item, i) => { ... });
| JS | Python |
|---|---|
for (const x of arr) |
for x in arr: |
arr.forEach((x, i) => ...) |
for i, x in enumerate(arr): |
for (const k in obj) |
for k in dict: |
⚠️ for...in 陷阱:JS 的 for...in 遍历键/索引,for...of 遍历值。Python 只有一个 for x in,遍历 list 时拿到的是值(相当于 JS 的 of),遍历 dict 时拿到的是键。
五、高阶函数:map / filter / reduce → 列表推导式
这是前端最该「忘掉旧写法」的地方。Python 虽然也有 map() / filter(),但社区强烈推荐用列表推导式(list comprehension),更短更地道。详见第 06 篇。
// JavaScript:链式方法
const doubled = nums.map(x => x * 2);
const evens = nums.filter(x => x % 2 === 0);
const result = nums.filter(x => x > 0).map(x => x * 2);
| JS | Python 推导式 |
|---|---|
arr.map(x => x * 2) |
[x * 2 for x in arr] |
arr.filter(x => x > 0) |
[x for x in arr if x > 0] |
arr.filter(f).map(g) |
[g(x) for x in arr if f(x)] |
Object.fromEntries(...) |
{k: v for k, v in items}(字典推导式) |
arr.reduce((a, b) => a + b, 0) |
sum(arr) 或 from functools import reduce |
⚠️ reduce 在 Python 里被「打入冷宫」,要从 functools 导入。能用 sum() / max() / min() 这些内置聚合函数就别用 reduce。
六、对象 / 字典(dict)
| JavaScript | Python | 说明 |
|---|---|---|
obj.key |
dict["key"] |
⚠️ Python 不能用点号访问字典 |
obj["key"] |
dict["key"] |
一致,但 key 不存在会抛 KeyError |
obj.key ?? "default" |
dict.get("key", "default") |
⚠️ 用 .get() 拿默认值,更安全 |
obj.key = v |
dict["key"] = v |
赋值/新增 |
delete obj.key |
del dict["key"] |
删除 |
"key" in obj |
"key" in dict |
判断键存在,一致 |
Object.keys(obj) |
dict.keys() |
所有键 |
Object.values(obj) |
dict.values() |
所有值 |
Object.entries(obj) |
dict.items() |
键值对 |
{...a, ...b} |
{**a, **b} |
⚠️ 展开用 **(字典)/ *(列表) |
obj?.a?.b |
无直接等价 | ⚠️ Python 没有可选链,用 .get() 逐层或 try |
// JavaScript:安全取值
const port = config.port ?? 8080;
⚠️ obj.key 不能套用:JS 里对象属性可以点号访问,Python 的 dict 只能用方括号。点号在 Python 里是「访问对象的属性/方法」,是另一回事(dict 没有叫 key 的属性)。
七、切片(slice)—— Python 的杀手锏
Python 的切片比 JS 强大得多,list / str / tuple 通用。语法 序列[起始:结束:步长],含头不含尾(和 JS slice 一致)。
// JavaScript
arr.slice(1, 3); // 索引 1~2
arr.slice(-2); // 最后两个
arr.slice().reverse() // 反转副本
| JS | Python |
|---|---|
arr.slice(1, 3) |
arr[1:3] |
arr.slice(-2) |
arr[-2:] |
arr.slice().reverse() |
arr[::-1] |
str[0] |
str[0] |
八、函数
8.1 声明对照
// JavaScript
function add(a, b = 0) { return a + b; }
const add = (a, b) => a + b; // 箭头函数
function sum(...nums) { ... } // 剩余参数
| JS | Python | 说明 |
|---|---|---|
function f(a, b) |
def f(a, b): |
|
(a, b) => a + b |
lambda a, b: a + b |
⚠️ lambda 只能单表达式 |
f(a, b = 1) |
def f(a, b=1): |
默认参数 |
f(...args) |
def f(*args): |
收集位置参数为 tuple |
| 无直接等价 | def f(**kwargs): |
收集关键字参数为 dict |
f(...arr) |
f(*arr) |
调用时展开 |
8.2 关键字参数(Python 特有,很爽)
⚠️ 可变默认参数大坑(前端最容易栽):默认参数 def f(items=[]) 的 [] 只在定义时创建一次,多次调用会共享同一个 list!这和 JS 完全不同。正确写法:
九、同名不同义的关键字(⚠️ 重灾区)
| JS | Python | ⚠️ 区别 |
|---|---|---|
=== |
== |
Python 的 == 比较「值」,没有 === |
==(带隐式转换) |
无 | Python == 不做 JS 那种松散转换 |
===(同一引用) |
is |
⚠️ is 比较「是不是同一个对象」,只用于和 None 比 |
! |
not |
逻辑非 |
&& |
and |
逻辑与 |
|| |
or |
逻辑或 |
a ? b : c |
b if a else c |
⚠️ 三元表达式顺序不同 |
null / undefined |
None |
|
typeof x |
type(x) |
|
x instanceof C |
isinstance(x, C) |
|
this |
self |
⚠️ 详见第 07 篇,self 必须手写为方法第一个参数 |
// JavaScript
const label = age >= 18 ? "成年" : "未成年";
if (user === null) { ... }
⚠️ is 不是 ===:别看到「严格相等」就用 is。is 判断的是「内存里是不是同一个对象」,比较数字/字符串会出诡异结果。记死规则:只在判断 is None / is not None 时用 is,其余一律 ==。
十、类与面向对象
// JavaScript
class User {
constructor(name) { this.name = name; }
greet() { return `Hi ${this.name}`; }
}
const u = new User("Tom");
| JS | Python | 说明 |
|---|---|---|
constructor() {} |
def __init__(self): |
构造方法 |
this |
self |
⚠️ 必须作为方法第一个参数显式声明 |
new User() |
User() |
⚠️ 没有 new |
class B extends A |
class B(A): |
继承 |
super() |
super().__init__() |
调父类构造 |
static method() |
@staticmethod |
静态方法用装饰器 |
get x() |
@property |
属性访问器 |
toString() |
__str__(self) |
转字符串(魔术方法) |
⚠️ self 不是 this:它不是关键字、不会自动注入,纯靠你手写。漏写第一个 self 参数是新手最高频报错。详见第 07 篇。
十一、异步 async / await
好消息:Python 的 async/await 写法和 JS 高度一致,心智模型基本能直接搬。机制差异(GIL、事件循环)详见第 17 篇,这里只对照写法。
// JavaScript
async function fetchData() {
const res = await fetch(url);
return await res.json();
}
await Promise.all([a(), b()]);
| JS | Python | 说明 |
|---|---|---|
async function |
async def |
|
await x |
await x |
一致 |
Promise.all([...]) |
asyncio.gather(...) |
并发聚合 |
setTimeout 配 Promise |
await asyncio.sleep(s) |
异步等待 |
| 顶层直接 await | asyncio.run(main()) |
⚠️ Python 要用 run 启动事件循环 |
⚠️ GIL ≠ 影响 async:很多人听说「Python 有 GIL 不能并发」就以为 async 没用。其实 async 处理的是 IO 等待(网络、磁盘),和 GIL(限制的是多线程跑 CPU 计算)是两码事。async 该快还是快,心智和 JS 单线程事件循环一模一样。详见第 17 篇。
十二、装饰器 ≈ TS/Angular 的 @Component
如果你写过 Angular 或 TS 的 @Component / @Injectable,那 Python 装饰器长得一模一样——@ 加在函数/类上面那行。机制详见第 10 篇。
// TypeScript / Angular:你已经见过的 @ 语法
@Component({ selector: "app" })
class AppComponent {}
机制一句话:@deco 加在 def f 上,等价于 f = deco(f)——拿原函数当参数、返回一个包装后的新函数。类比 JS 里「中间件包一层 handler」。详见第 10 篇。
十三、生成器 ≈ function / yield
JS 的 function* + yield 在 Python 里几乎一对一映射——只是少了那个 *。详见第 06 篇。
// JavaScript
function* counter() {
let i = 0;
while (true) yield i++;
}
| JS | Python |
|---|---|
function* g() |
def g():(函数体里有 yield) |
yield x |
yield x |
yield* iter |
yield from iter |
gen.next().value |
next(gen) |
十四、异常处理
// JavaScript
try {
risky();
} catch (e) {
console.error(e);
} finally {
cleanup();
}
throw new Error("boom");
| JS | Python | 说明 |
|---|---|---|
try {} |
try: |
|
catch (e) |
except Exception as e: |
⚠️ 关键字是 except |
finally {} |
finally: |
一致 |
throw new Error(x) |
raise ValueError(x) |
⚠️ 用 raise,不用 new |
| 无直接等价 | with open(f) as fp: |
上下文管理器,自动关资源,详见第 09 篇 |
⚠️ Python 鼓励按类型分别 except(except ValueError / except KeyError),比 JS 里一个 catch 里 if (e instanceof ...) 优雅。
十五、模块与导入
| JavaScript | Python | 说明 |
|---|---|---|
import { a, b } from "./m" |
from m import a, b |
按名导入 |
import * as m from "./m" |
import m |
整模块导入,用 m.a 调 |
import x from "./m" |
无默认导出概念 | ⚠️ Python 没有 default export |
export const a = 1 |
a = 1(模块内顶层变量自动可导入) |
⚠️ 不写 export,默认全部可被导入 |
import("./m") 动态 |
importlib.import_module("m") |
动态导入 |
package.json |
requirements.txt / pyproject.toml |
依赖清单,详见第 12 篇 |
npm install x |
pip install x |
装包 |
node_modules/ |
.venv/(虚拟环境) |
⚠️ 隔离方式不同,详见第 12 篇 |
十六、Web 后端:FastAPI ≈ Express
写过 Express 路由的话,FastAPI 几乎是「带类型校验的 Express」。详见第 14、15 篇。
// Express
app.get("/users/:id", (req, res) => {
res.json({ id: req.params.id });
});
| Express | FastAPI | 说明 |
|---|---|---|
app.get("/p/:id", fn) |
@app.get("/p/{id}") |
路径参数花括号 |
req.params.id |
函数参数 id |
自动注入 |
req.query.q |
函数参数(带默认值) | query 参数 |
req.body |
Pydantic 模型参数 | ⚠️ 自动校验,≈ zod,详见第 15 篇 |
res.json(obj) |
return obj |
直接 return |
| 手写校验 | Pydantic BaseModel |
像 zod / TS interface 但运行时真校验 |
express.Router() |
APIRouter() |
路由分组 |
十七、数据处理三件套(阶段四锚点)
这三个库前端没有对应物,必须建立类比锚点,否则容易被 API 淹没。详见第 20、21、22 篇。
17.1 NumPy ≈ 批量操作的「超级 Array」
把 NumPy 数组想成一个能整体做数学运算的 JS Array——不用写 for 循环逐个处理,整个数组一把梭。
// JavaScript:逐个 for / map
const a = [1, 2, 3];
const doubled = a.map(x => x * 2); // 必须遍历
锚点:
np.array≈ 批量操作版的 Array,a * 2替代a.map(x => x*2),这种「整体运算」叫向量化,是 NumPy 快的原因。
17.2 Pandas DataFrame ≈ 加强版 Excel / SQL
DataFrame 就是代码里的一张表:有行有列、能筛选、能分组聚合,约等于「Excel 表格 + SQL 查询」的合体。
锚点:选列 ≈ SELECT,
df[条件]≈ WHERE,groupby≈ GROUP BY。把它当「能写代码的 Excel」就不慌。
17.3 matplotlib ≈ 后端版 ECharts / D3
画图库,相当于在 Python 里用 ECharts——给数据、选图表类型、出图。
锚点:
plt.plot≈ ECharts line,plt.bar≈ bar。区别是它跑在后端,结果常存成 png 而不是渲染到 DOM。
十八、AI 编程速查(阶段五锚点)
阶段五的依赖链:23 调模型 → 24 函数调用 → 25 Embedding → 26 RAG → 27 Agent,一篇比一篇陡。这里只给最小心智锚点,细节回各专题篇。
18.1 调大模型 ≈ 调一个 REST API
锚点:
messages≈ 一个对话记录数组,调用 ≈ 一次带 body 的 POST,区别只是 SDK 帮你拼好了。详见第 23 篇。
18.2 Embedding ≈ 把文字压成一串坐标
别被「向量」吓到。想想 CSS 颜色 rgb(255, 0, 0)——它就是个三维向量,颜色越接近、数值距离越近。Embedding 就是同理:把一段文字压成一长串数字(坐标),语义相近的文字,坐标点挨得近。检索 = 在坐标空间里找最近的点。详见第 25 篇。
锚点:RGB 是三维向量、颜色相近=距离近;Embedding 是高维向量、语义相近=距离近。检索就是「找最近的点」。
18.3 RAG ≈ 先查资料再回答
RAG = 检索增强生成。流程:把文档切块(chunking)→ 各块转 Embedding 存库 → 用户提问时检索最相关的块 → 把块塞进 prompt 让模型基于它回答。本质是「开卷考试」:先翻到相关那几页,再答题。详见第 26 篇。
锚点:检索(找最近的点,见 17.2)+ 拼 prompt(字符串模板)+ 生成(调模型,见 17.1)。每步你都见过,RAG 只是把它们串起来。
18.4 Agent / 工具调用 ≈ 带记忆的 while 循环 + 函数注册表
- tool use(工具调用) ≈ 给模型注册一组可调用函数(类似事件回调/函数注册表)。你描述好每个函数干啥、要什么参数,模型决定何时调哪个。
- ReAct ≈ 一个
while循环:反复「思考 → 调用工具(像调 API)→ 拿结果再思考」,直到得出答案。 - 多步推理 = 这个循环带着记忆(历史 messages)一轮轮跑。
锚点:tool use ≈ 函数注册表(像注册事件回调),ReAct ≈
while(思考→调工具→拿结果),多步推理 = 带记忆的循环。这三个你在前端全见过。详见第 27 篇。
十九、命令行 / 工程速查(node 生态对照)
| Node 生态 | Python 生态 | 说明 |
|---|---|---|
node app.js |
python app.py |
运行脚本 |
npm init |
python -m venv .venv |
初始化环境(详见第 12 篇) |
npm install x |
pip install x |
装包 |
npm install |
pip install -r requirements.txt |
按清单装 |
package.json |
requirements.txt / pyproject.toml |
依赖清单 |
node_modules/ |
.venv/ |
依赖隔离目录 |
npx |
pipx / python -m |
跑工具 |
console.log(x) |
print(x) |
打印 |
JSON.stringify(o) |
json.dumps(o) |
对象转 JSON 字符串 |
JSON.parse(s) |
json.loads(s) |
JSON 字符串转对象 |
⚠️ 虚拟环境是 Python 必备习惯:不像 node_modules 默认本地隔离,Python 默认全局装包会污染系统。每个项目先 python -m venv .venv 再 source .venv/bin/activate,养成习惯。详见第 12 篇。
二十、命名风格对照
| 场景 | JS/TS 习惯 | Python 习惯(PEP 8) |
|---|---|---|
| 变量/函数 | camelCase |
snake_case |
| 类名 | PascalCase |
PascalCase(一致) |
| 常量 | UPPER_CASE |
UPPER_CASE(一致) |
| 私有 | #field / _field |
_field(单下划线约定) |
| 文件名 | userService.ts |
user_service.py |
⚠️ 别把 JS 的 camelCase 带进 Python。社区强约定用 snake_case,混用会被一眼看出「这是个写 JS 的人」。
二十一、总结
- 怎么用本篇:表格里凡是标了 ⚠️ 的,都是长得像但行为不一样的坑,看到必须停一下。
- 变量与基本类型:⚠️ 三个最容易写错的常量:JS 的 true / false / null 在 Python 里是 True / False / None(首字母大写),写小写直接 NameError。
- 字符串操作:| str.length | len(str) | ⚠️ 不是属性,是内置函数 len() |
- 数组 / 列表(list):| arr.indexOf(x) | arr.index(x) | ⚠️ 找不到 Python 会抛异常,不是返回 -1 |
- 高阶函数:map / filter / reduce → 列表推导式:这是前端最该「忘掉旧写法」的地方。
- 对象 / 字典(dict):| obj.key | dict["key"] | ⚠️ Python 不能用点号访问字典 |