侧边栏壁纸
博主头像
前端学习

行动起来,活在当下

  • 累计撰写 313 篇文章
  • 累计创建 18 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Python 与 TypeScript 对照手册

Administrator
2026-06-05 / 0 评论 / 0 点赞 / 3 阅读 / 0 字

Python 与 TypeScript 对照手册

把常见 TS/JS -> Python 的概念、语法、类型、方法、函数、工程习惯做成可对照、可回查的手册。

第一部分:学习路径

1. 环境与运行方式

1.1 运行 Python

概念定义

Python 既可以像 Node 一样直接执行脚本,也可以进入 REPL 交互环境一行一行试代码。

前端/TS 心智模型

  • python demo.py 类似 node demo.js
  • python 进入交互环境,类似浏览器 Console 或 node REPL

Python 写法

python --version
python
python app.py

TS 对照写法

node --version
node
node app.js

差异提醒

  • Python 一般不需要先编译成 JS 再运行。
  • .py 文件默认按解释执行,不像 TS 需要 tsc 或运行时工具链支持。

常见坑

  • 系统里可能同时有 pythonpy 启动器,Windows 下都很常见。
  • 安装完 Python 要确认 pip 和虚拟环境都可用。

最小示例

print("hello python")  # hello python
console.log("hello typescript"); // hello typescript

1.2 脚本入口

概念定义

Python 模块既可以被导入,也可以被直接运行。if __name__ == "__main__": 用来区分这两种场景。

前端/TS 心智模型

它有点像 Node 里的 if (require.main === module),只是写法不同。

Python 写法

def main():
    print("run app")  # run app

if __name__ == "__main__":
    main()

TS 对照写法

function main() {
  console.log("run app"); // run app
}

if (require.main === module) {
  main();
}

差异提醒

  • Python 模块导入时会执行顶层代码,所以脚本入口判断很重要。

常见坑

  • 把测试代码直接写在模块顶层,导致导入时自动执行。

2. 基础语法与语句块

2.1 缩进而不是花括号

概念定义

Python 用缩进表示代码块,不用 {}

前端/TS 心智模型

可以把缩进理解成“语法的一部分”,不是单纯代码风格。

Python 写法

age = 20

if age >= 18:
    print("adult")  # adult
else:
    print("minor")  # 这个分支当前不会执行

TS 对照写法

const age = 20;

if (age >= 18) {
  console.log("adult"); // adult
} else {
  console.log("minor"); // 这个分支当前不会执行
}

差异提醒

  • Python 里同级代码必须对齐。
  • 冒号 : 常用于开启一个代码块。

常见坑

  • 混用 tab 和空格。
  • 少缩进或多缩进会直接语法报错。

2.2 注释与文档字符串

概念定义

  • 单行注释用 #
  • 多行说明通常用三引号字符串 """...""",函数/类/模块顶部常作为文档字符串

Python 写法

# 这是单行注释

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

TS 对照写法

// 这是单行注释

/**
 * 返回两个数之和
 */
function add(a: number, b: number) {
  return a + b;
}

差异提醒

  • Python 的三引号本质上是字符串,不是专用注释语法。

3. 变量、绑定与基础类型

3.1 变量绑定

概念定义

Python 没有 var / let / const。名字只是“绑定到某个对象”的引用。

前端/TS 心智模型

更像“所有变量声明都只有一种形式”,但“对象是否可变”与“变量名是否可重新赋值”不是同一个维度。

Python 写法

name = "Alice"
age = 18
age = 19

TS 对照写法

let name = "Alice";
let age = 18;
age = 19;

差异提醒

  • Python 不靠 const 表达常量约束。
  • 约定俗成会把常量写成全大写,如 MAX_RETRY = 3,但语言层不阻止修改。

常见坑

  • 误以为 Python 名字重新赋值和对象内部修改是同一种操作。

最小示例

items = [1, 2]
alias = items
items.append(3)
print(alias)  # [1, 2, 3]
const items = [1, 2];
const alias = items;
items.push(3);
console.log(alias); // [1, 2, 3]

3.2 intfloatboolstrNone

整数与浮点数

count = 10
price = 19.9
total = count * price  # 199.0
const count: number = 10;
const price: number = 19.9;
const total = count * price; // 199

差异点:

  • TS/JS 的 number 同时覆盖整数和浮点数。
  • Python 则区分 intfloat

布尔值

is_admin = True   # True
is_done = False   # False
const isAdmin = true;  // true
const isDone = false;  // false

差异点:

  • Python 布尔值首字母大写:True / False

字符串

name = "Alice"  # "Alice"
message = f"hello, {name}"  # "hello, Alice"
multi = """
line1
line2
"""  # 包含换行的多行字符串
const name = "Alice"; // "Alice"
const message = `hello, ${name}`; // "hello, Alice"
const multi = `
line1
line2
`; // 包含换行的多行字符串

差异点:

  • Python 常用 f"..." 做字符串插值。
  • Python 三引号支持多行字符串。

空值 None

result = None
if result is None:
    print("empty")  # empty
let result: string | null = null;
if (result === null) {
  console.log("empty"); // empty
}

差异点:

  • None 更接近 JS 里的 null
  • 判断 None 推荐用 is None,不要用 == None

常见坑

  • if value: 会把 0""[]{}None 都视为假值。

4. 容器类型

4.1 list 对照 Array

概念定义

list 是 Python 最常用的有序可变容器。

前端/TS 心智模型

它最接近 JS 的 Array,但并不是方法一一对应;很多能力来自内置函数和语法。

Python 写法

nums = [1, 2, 3]
nums.append(4)        # [1, 2, 3, 4]
nums.extend([5, 6])   # [1, 2, 3, 4, 5, 6]
first = nums[0]       # 1
last = nums[-1]       # 6
part = nums[1:3]      # [2, 3]

TS 对照写法

const nums = [1, 2, 3];
nums.push(4); // [1, 2, 3, 4]
nums.push(...[5, 6]); // [1, 2, 3, 4, 5, 6]
const first = nums[0]; // 1
const last = nums[nums.length - 1]; // 6
const part = nums.slice(1, 3); // [2, 3]

常见方法对照

PythonTS/JS 近似说明
append(x)push(x)末尾追加一个元素
extend(xs)push(...xs)追加多个元素
insert(i, x)splice(i, 0, x)在指定位置插入
pop()pop()弹出末尾元素
remove(x)splice(index, 1)按值删除第一个匹配项
sort()sort()原地排序
reverse()reverse()原地反转
count(x)filter(...).length统计出现次数
index(x)indexOf(x)查找位置

最小示例

users = ["a", "b", "c"]
users.remove("b")
print(users)  # ['a', 'c']
const users = ["a", "b", "c"];
users.splice(users.indexOf("b"), 1);
console.log(users); // ["a", "c"]

4.2 tuple

概念定义

tuple 是有序不可变序列。

前端/TS 心智模型

最接近 TS 里的元组类型或只读定长数组。

Python 写法

point = (10, 20)  # (10, 20)
x, y = point      # x == 10, y == 20

TS 对照写法

const point: [number, number] = [10, 20]; // [10, 20]
const [x, y] = point; // x === 10, y === 20

差异提醒

  • Python 元组更常用于“不可变的小结构”或“多返回值”。

4.3 dict 对照对象/Map

概念定义

dict 是键值映射。

前端/TS 心智模型

它有时像普通对象 {},有时又更接近 Map。不要把它简单当成 JS 对象的翻版。

Python 写法

user = {"name": "Alice", "age": 18}
name = user["name"]        # "Alice"
age = user.get("age", 0)   # 18
user["city"] = "Shanghai"  # {"name": "Alice", "age": 18, "city": "Shanghai"}

TS 对照写法

const user = { name: "Alice", age: 18 };
const name = user.name; // "Alice"
const age = user.age ?? 0; // 18
Object.assign(user, { city: "Shanghai" }); // { name: "Alice", age: 18, city: "Shanghai" }

常见方法对照

PythonTS/JS 近似说明
d.keys()Object.keys(obj)获取键
d.values()Object.values(obj)获取值
d.items()Object.entries(obj)获取键值对
d.get(k, default)obj[k] ?? default安全取值
d.pop(k)delete obj[k] 前先取值删除并返回值
d.update(other)Object.assign(obj, other)合并

差异提醒

  • Python dict 的键不局限于字符串。
  • obj.key 风格在 Python 字典里不成立,必须 user["name"]user.get("name")

常见坑

  • 直接取不存在的键会抛 KeyError

4.4 set

概念定义

set 是无序不重复集合。

前端/TS 心智模型

几乎对应 JS 的 Set

Python 写法

tags = {"python", "ts"}
tags.add("react")       # {"python", "ts", "react"}
has_ts = "ts" in tags   # True

TS 对照写法

const tags = new Set(["python", "ts"]);
tags.add("react"); // Set { "python", "ts", "react" }
const hasTs = tags.has("ts"); // true

常见操作

a = {1, 2, 3}
b = {3, 4, 5}
print(a | b)  # {1, 2, 3, 4, 5},并集
print(a & b)  # {3},交集
print(a - b)  # {1, 2},差集
const a = new Set([1, 2, 3]);
const b = new Set([3, 4, 5]);
const union = new Set([...a, ...b]); // Set { 1, 2, 3, 4, 5 }
const intersection = new Set([...a].filter(v => b.has(v))); // Set { 3 }
const diff = new Set([...a].filter(v => !b.has(v))); // Set { 1, 2 }

5. 运算、比较与切片

5.1 比较与逻辑运算

age = 20
passed = age >= 18 and age < 60  # True
is_guest = not False             # True
const age = 20;
const passed = age >= 18 && age < 60; // true
const isGuest = !false; // true

差异点:

  • Python 用 and / or / not
  • TS/JS 用 && / || / !

5.2 成员判断

nums = [1, 2, 3]
print(2 in nums)      # True
print(5 not in nums)  # True
const nums = [1, 2, 3];
console.log(nums.includes(2)); // true
console.log(!nums.includes(5)); // true

5.3 切片

text = "abcdef"
print(text[1:4])   # bcd;[1:4] 表示从下标 1 取到下标 4 前,不包含 4
print(text[:3])    # abc;[:3] 省略起始位置,表示从开头取到下标 3 前
print(text[::2])   # ace;[::2] 表示从头到尾每隔 2 个字符取 1 个
print(text[::-1])  # fedcba;[::-1] 表示倒序切片,常用来反转字符串或列表
const text = "abcdef";
console.log(text.slice(1, 4));
console.log(text.slice(0, 3));
console.log([...text].filter((_, i) => i % 2 === 0).join(""));
console.log([...text].reverse().join(""));

差异点:

  • Python 切片适用于字符串、列表、元组。
  • [::-1] 是非常常见的反转技巧。

6. 流程控制

6.1 if / elif / else

score = 88

if score >= 90:
    level = "A"
elif score >= 80:
    level = "B"
else:
    level = "C"

# level == "B"
const score = 88;
let level = "";

if (score >= 90) {
  level = "A";
} else if (score >= 80) {
  level = "B";
} else {
  level = "C";
}

// level === "B"

6.2 for 循环

概念定义

Python 的 for ... in ... 是遍历“可迭代对象”,不是 JS 里那种遍历对象键名的 for...in

for item in [10, 20, 30]:
    print(item)
for (const item of [10, 20, 30]) {
  console.log(item);
}

差异提醒

  • Python 的 for item in list 更像 TS 的 for...of
  • JS 的 for...in 更像遍历对象键

6.3 range

for i in range(5):
    print(i)  # 依次输出 0、1、2、3、4;range(5) 会生成 0 到 4
for (let i = 0; i < 5; i++) {
  console.log(i); // 依次输出 0、1、2、3、4;这里用 i++ 手动控制下标
}

6.4 while

count = 0
while count < 3:
    print(count)  # 依次输出 0、1、2
    count += 1
let count = 0;
while (count < 3) {
  console.log(count); // 依次输出 0、1、2
  count += 1;
}

6.5 match

Python 3.10+ 有结构化模式匹配,类似更强的 switch

status = 404

match status:
    case 200:
        text = "ok"
    case 404:
        text = "not found"
    case _:
        text = "unknown"

# text == "not found"
const status = 404;
let text = "";

switch (status) {
  case 200:
    text = "ok";
    break;
  case 404:
    text = "not found";
    break;
  default:
    text = "unknown";
}

// text === "not found"

7. 函数

7.1 基本函数定义

def add(a, b):
    return a + b
function add(a: number, b: number) {
  return a + b;
}

7.2 类型注解版函数

def add(a: int, b: int) -> int:
    return a + b  # 例如 add(1, 2) 返回 3
function add(a: number, b: number): number {
  return a + b; // 例如 add(1, 2) 返回 3
}

7.3 默认参数

def greet(name: str, prefix: str = "Hello") -> str:
    return f"{prefix}, {name}"  # 例如 greet("Alice") 返回 "Hello, Alice"
function greet(name: string, prefix = "Hello"): string {
  return `${prefix}, ${name}`; // 例如 greet("Alice") 返回 "Hello, Alice"
}

7.4 关键字参数

def create_user(name: str, age: int, city: str = "Shanghai"):
    return {"name": name, "age": age, "city": city}

user = create_user(age=18, name="Alice")  # {"name": "Alice", "age": 18, "city": "Shanghai"};关键字参数按参数名传值,所以顺序可以调整
function createUser({
  name,
  age,
  city = "Shanghai",
}: {
  name: string;
  age: number;
  city?: string;
}) {
  return { name, age, city };
}

const user = createUser({ age: 18, name: "Alice" });
// { name: "Alice", age: 18, city: "Shanghai" }

差异点:

  • Python 没有对象参数解构那种默认模式,关键字参数是另一套机制。

7.5 可变参数

def sum_all(*nums: int) -> int:
    return sum(nums)  # *nums 会把多个位置参数收集成 tuple;例如 sum_all(1, 2, 3) 返回 6

def print_profile(**kwargs):
    print(kwargs)  # **kwargs 会把多个具名参数收集成 dict;例如 print_profile(name="Alice", age=18) 会打印 {"name": "Alice", "age": 18}
function sumAll(...nums: number[]): number {
  return nums.reduce((acc, n) => acc + n, 0); // ...nums 会把多个参数收集成数组;例如 sumAll(1, 2, 3) 返回 6
}

function printProfile(kwargs: Record<string, unknown>) {
  console.log(kwargs); // 例如 { name: "Alice", age: 18 }
}

7.6 多返回值

def min_max(nums: list[int]) -> tuple[int, int]:
    return min(nums), max(nums)

low, high = min_max([3, 1, 9])  # low == 1, high == 9
function minMax(nums: number[]): [number, number] {
  return [Math.min(...nums), Math.max(...nums)];
}

const [low, high] = minMax([3, 1, 9]); // low === 1, high === 9

7.7 lambda

nums = [3, 1, 2]
sorted_nums = sorted(nums, key=lambda x: x)  # [1, 2, 3];key= 指定排序依据,lambda x: x 表示按元素本身排序
const nums = [3, 1, 2];
const sortedNums = [...nums].sort((a, b) => a - b); // [1, 2, 3];a - b 这个比较函数表示按数值升序排序

差异点:

  • Python 的 lambda 只能写单表达式,不能写多行函数体。

7.8 作用域

count = 0

def inc():
    global count
    count += 1  # 调用一次后 count == 1;global count 表示这里修改的是外部同名变量
let count = 0;

function inc() {
  count += 1; // 调用一次后 count === 1;这里默认就会修改外层作用域变量
}

差异点:

  • Python 在函数里赋值会默认创建局部变量,想改外部变量要显式 globalnonlocal

高频坑:默认可变参数

def append_item(item, bucket=[]):
    bucket.append(item)
    return bucket

print(append_item(1))  # [1]
print(append_item(2))  # [1, 2]

正确写法:

def append_item(item, bucket=None):
    if bucket is None:
        bucket = []
    bucket.append(item)
    return bucket

TS 对照:

function appendItem(item: number, bucket: number[] = []) {
  bucket.push(item);
  return bucket;
}

8. 常用语法糖

8.1 解包

point = (10, 20)
x, y = point  # x == 10, y == 20;这是序列解包,右边会按顺序拆给左边变量

first, *rest = [1, 2, 3, 4]  # first == 1, rest == [2, 3, 4];*rest 表示把剩余元素都收集起来
const point: [number, number] = [10, 20];
const [x, y] = point; // x === 10, y === 20;数组解构会按顺序拆值

const [first, ...rest] = [1, 2, 3, 4]; // first === 1, rest === [2, 3, 4];...rest 收集剩余元素

8.2 合并列表和字典

nums = [1, 2]
merged = [0, *nums, 3]  # [0, 1, 2, 3];*nums 会把列表里的元素逐个展开

user = {"name": "Alice"}
full = {**user, "age": 18}  # {"name": "Alice", "age": 18};**user 会把字典里的键值对展开后再合并
const nums = [1, 2];
const merged = [0, ...nums, 3]; // [0, 1, 2, 3];...nums 会把数组元素展开

const user = { name: "Alice" };
const full = { ...user, age: 18 }; // { name: "Alice", age: 18 };...user 会把对象属性展开

8.3 列表推导式

nums = [1, 2, 3, 4]
squares = [n * n for n in nums]  # [1, 4, 9, 16];列表推导式会遍历 nums 并生成一个新列表
even_squares = [n * n for n in nums if n % 2 == 0]  # [4, 16];if 条件表示先过滤偶数,再生成结果
const nums = [1, 2, 3, 4];
const squares = nums.map(n => n * n); // [1, 4, 9, 16]
const evenSquares = nums.filter(n => n % 2 === 0).map(n => n * n); // [4, 16]

8.4 字典推导式与集合推导式

nums = [1, 2, 3]
mapping = {n: n * n for n in nums}  # {1: 1, 2: 4, 3: 9};字典推导式会生成键值映射
unique_lengths = {len(name) for name in ["a", "bb", "ccc", "bb"]}  # {1, 2, 3};集合推导式会自动去重
const nums = [1, 2, 3];
const mapping = Object.fromEntries(nums.map(n => [n, n * n])); // { 1: 1, 2: 4, 3: 9 }
const uniqueLengths = new Set(["a", "bb", "ccc", "bb"].map(name => name.length)); // Set { 1, 2, 3 }

8.5 enumeratezip

names = ["a", "b", "c"]
for index, name in enumerate(names):
    print(index, name)  # 依次输出 0 a、1 b、2 c;enumerate 会同时给出索引和值

for left, right in zip([1, 2], ["a", "b"]):
    print(left, right)  # 依次输出 1 a、2 b;zip 会按位置把多个序列一一配对
const names = ["a", "b", "c"];
names.forEach((name, index) => console.log(index, name)); // 依次输出 0 a、1 b、2 c;forEach 回调里可以同时拿到值和索引

[[1, "a"], [2, "b"]].forEach(([left, right]) => console.log(left, right)); // 依次输出 1 a、2 b;这里手动构造了配对后的二维数组

9. 字符串、列表、字典常用方法

9.1 字符串方法

text = " hello,Python "
print(text.strip())                 # "hello,Python"
print(text.lower())                # " hello,python "
print(text.upper())                # " HELLO,PYTHON "
print(text.replace("Python", "TS"))  # " hello,TS "
print(text.split(","))             # [" hello", "Python "]
print(",".join(["a", "b", "c"]))   # "a,b,c"
print("python".startswith("py"))   # True
print("python".endswith("on"))     # True
const text = " hello,Python ";
console.log(text.trim()); // "hello,Python"
console.log(text.toLowerCase()); // " hello,python "
console.log(text.toUpperCase()); // " HELLO,PYTHON "
console.log(text.replace("Python", "TS")); // " hello,TS "
console.log(text.split(",")); // [" hello", "Python "]
console.log(["a", "b", "c"].join(",")); // "a,b,c"
console.log("python".startsWith("py")); // true
console.log("python".endsWith("on")); // true

9.2 列表方法

nums = [3, 1, 2]
nums.sort()          # [1, 2, 3]
nums.reverse()       # [3, 2, 1]
print(nums.count(1)) # 1
print(nums.index(3)) # 0
const nums = [3, 1, 2];
nums.sort((a, b) => a - b); // [1, 2, 3]
nums.reverse(); // [3, 2, 1]
console.log(nums.filter(n => n === 1).length); // 1
console.log(nums.indexOf(3)); // 0

9.3 字典方法

user = {"name": "Alice", "age": 18}
print(user.keys())                 # dict_keys(["name", "age"])
print(user.values())               # dict_values(["Alice", 18])
print(user.items())                # dict_items([("name", "Alice"), ("age", 18)])
print(user.get("city", "unknown")) # "unknown"
user.update({"city": "Shanghai"})  # {"name": "Alice", "age": 18, "city": "Shanghai"}
const user = { name: "Alice", age: 18 };
console.log(Object.keys(user)); // ["name", "age"]
console.log(Object.values(user)); // ["Alice", 18]
console.log(Object.entries(user)); // [["name", "Alice"], ["age", 18]]
console.log(user["city" as keyof typeof user] ?? "unknown"); // "unknown"
Object.assign(user, { city: "Shanghai" }); // { name: "Alice", age: 18, city: "Shanghai" }

10. 模块、包与导入

10.1 导入模块

import math
from pathlib import Path
from utils import add
import path from "node:path";
import { add } from "./utils";

差异提醒

  • Python 导入靠模块路径,不是文件扩展名。
  • 一个目录里通常需要合理的包结构,尤其是多文件项目。

10.2 模块示例

utils.py

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

main.py

from utils import add

print(add(1, 2))  # 3

TS 对照:

utils.ts

export function add(a: number, b: number) {
  return a + b;
}

main.ts

import { add } from "./utils";

console.log(add(1, 2)); // 3

常见坑

  • 直接在错误目录运行脚本,导致相对导入失败。
  • 当前工作目录和模块搜索路径不是一回事。

11. 异常处理

11.1 try / except / finally

try:
    value = int("123")
except ValueError as err:
    print("convert failed", err)  # 当前不会进入这个分支
else:
    print("success", value)  # success 123
finally:
    print("done")  # done
try {
  const value = Number.parseInt("123", 10);
  if (Number.isNaN(value)) {
    throw new Error("convert failed");
  }
  console.log("success", value); // success 123
} catch (err) {
  console.log("convert failed", err); // 当前不会进入这个分支
} finally {
  console.log("done"); // done
}

差异提醒

  • Python 有更明确的异常类型体系,常按具体异常类型捕获。
  • else 块表示“没有异常时执行”。

11.2 主动抛错

def divide(a: float, b: float) -> float:
    if b == 0:
        raise ValueError("b cannot be 0")
    return a / b
function divide(a: number, b: number): number {
  if (b === 0) {
    throw new Error("b cannot be 0");
  }
  return a / b;
}

12. 文件操作与上下文管理器

12.1 读写文件

with open("demo.txt", "w", encoding="utf-8") as f:
    f.write("hello")  # demo.txt 里会写入 hello

with open("demo.txt", "r", encoding="utf-8") as f:
    content = f.read()  # "hello"
import { promises as fs } from "node:fs";

await fs.writeFile("demo.txt", "hello", "utf-8"); // demo.txt 里会写入 hello
const content = await fs.readFile("demo.txt", "utf-8"); // "hello"

差异提醒

  • with 会自动释放资源,很像 try/finally 的语法糖。

12.2 上下文管理器

class Timer:
    def __enter__(self):
        print("start")  # start
        return self

    def __exit__(self, exc_type, exc, tb):
        print("end")  # end

with Timer():
    print("running")  # running
async function withTimer(fn: () => Promise<void> | void) {
  console.log("start"); // start
  try {
    await fn();
  } finally {
    console.log("end"); // end
  }
}

13. 类、对象与面向对象

13.1 基本类

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

    def greet(self) -> str:
        return f"Hi, I am {self.name}"

user = User("Alice", 18)
print(user.greet())  # Hi, I am Alice
class User {
  constructor(public name: string, public age: number) {}

  greet(): string {
    return `Hi, I am ${this.name}`;
  }
}

const user = new User("Alice", 18);
console.log(user.greet()); // Hi, I am Alice

差异提醒

  • Python 实例方法第一个参数必须显式写 self
  • 构造函数叫 __init__

13.2 继承

class Admin(User):
    def greet(self) -> str:
        return f"Admin: {self.name}"  # 例如返回 "Admin: Alice"
class Admin extends User {
  override greet(): string {
    return `Admin: ${this.name}`; // 例如返回 "Admin: Alice"
  }
}

13.3 dataclass

概念定义

dataclass 用于快速定义“主要存数据”的类,减少样板代码。

from dataclasses import dataclass

@dataclass
class Product:
    name: str
    price: float

product = Product("Keyboard", 99.9)  # Product(name="Keyboard", price=99.9)
class Product {
  constructor(public name: string, public price: number) {}
}

const product = new Product("Keyboard", 99.9); // Product { name: "Keyboard", price: 99.9 }

14. 迭代器与生成器

14.1 可迭代对象

Python 里很多对象都能用于 for 循环,只要它们实现迭代协议。

for ch in "abc":
    print(ch)  # 依次输出 a、b、c
for (const ch of "abc") {
  console.log(ch); // 依次输出 a、b、c
}

14.2 生成器

def countdown(n: int):
    while n > 0:
        yield n  # yield 会逐个产出值,函数因此变成生成器
        n -= 1

for item in countdown(3):
    print(item)  # 依次输出 3、2、1;for 会逐个取出 yield 产出的值
function* countdown(n: number) {
  while (n > 0) {
    yield n; // yield 会逐个产出值,函数因此变成 generator
    n -= 1;
  }
}

for (const item of countdown(3)) {
  console.log(item); // 依次输出 3、2、1;for...of 会逐个取出 generator 产出的值
}

差异提醒

  • Python 生成器和 JS generator 很像,但 Python 在数据处理场景里更常见。

15. 装饰器

15.1 基本装饰器

概念定义

装饰器本质上是“接收函数并返回新函数的函数”。

def logger(fn):
    def wrapper(*args, **kwargs):
        print("before")  # before
        result = fn(*args, **kwargs)
        print("after")   # after
        return result
    return wrapper

@logger
def add(a, b):
    return a + b  # 调用 add(1, 2) 时最终返回 3
function logger<T extends (...args: any[]) => any>(fn: T) {
  return (...args: Parameters<T>): ReturnType<T> => {
    console.log("before"); // before
    const result = fn(...args);
    console.log("after"); // after
    return result;
  };
}

const add = logger((a: number, b: number) => a + b); // 调用 add(1, 2) 时最终返回 3

差异提醒

  • Python 装饰器语法 @decorator 非常常见。
  • 前端里更常见的是高阶函数、高阶组件、middleware 思维。

16. 类型注解与 typing

16.1 常见类型注解

name: str = "Alice"              # "Alice"
age: int = 18                    # 18
scores: list[int] = [1, 2, 3]    # [1, 2, 3]
user: dict[str, int] = {"age": 18}  # {"age": 18}
const name: string = "Alice"; // "Alice"
const age: number = 18; // 18
const scores: number[] = [1, 2, 3]; // [1, 2, 3]
const user: Record<string, number> = { age: 18 }; // { age: 18 }

16.2 Optional / 联合类型

from typing import Optional

nickname: Optional[str] = None  # None
let nickname: string | null = null; // null

16.3 TypedDict

from typing import TypedDict

class UserDict(TypedDict):
    name: str
    age: int

user: UserDict = {"name": "Alice", "age": 18}  # {"name": "Alice", "age": 18}
type UserDict = {
  name: string;
  age: number;
};

const user: UserDict = { name: "Alice", age: 18 }; // { name: "Alice", age: 18 }

16.4 泛型

from typing import TypeVar

T = TypeVar("T")

def first(items: list[T]) -> T:
    return items[0]  # 例如 first([10, 20, 30]) 返回 10
function first<T>(items: T[]): T {
  return items[0]; // 例如 first([10, 20, 30]) 返回 10
}

差异提醒

  • Python 类型注解默认不在运行时强校验,它更多服务于编辑器、静态检查和团队可读性。

17. 异步编程

17.1 async / await

import asyncio

async def fetch_data():
    await asyncio.sleep(1)
    return {"ok": True}  # {"ok": True}

async def main():
    result = await fetch_data()
    print(result)  # {'ok': True}

asyncio.run(main())
async function fetchData() {
  await new Promise(resolve => setTimeout(resolve, 1000));
  return { ok: true }; // { ok: true }
}

async function main() {
  const result = await fetchData();
  console.log(result); // { ok: true }
}

main();

差异提醒

  • Python async 常基于 asyncio 事件循环。
  • 它和浏览器/Node 的 Promise 模型相似,但不是同一套 API。

17.2 并发任务

import asyncio

async def task(name: str, delay: int):
    await asyncio.sleep(delay)
    return name  # 返回对应任务名

async def main():
    result = await asyncio.gather(task("a", 1), task("b", 2))  # gather 会并发等待多个协程并把结果收集成列表
    print(result)  # ['a', 'b']
async function task(name: string, delay: number) {
  await new Promise(resolve => setTimeout(resolve, delay * 1000));
  return name; // 返回对应任务名
}

async function main() {
  const result = await Promise.all([task("a", 1), task("b", 2)]); // Promise.all 会并发等待多个 Promise 并收集结果
  console.log(result); // ["a", "b"]
}

常见坑

  • 忘了 await
  • 把同步阻塞代码塞进 async 函数里,以为自动变非阻塞

18. 常用标准库映射

场景PythonTS/JS / Node
路径处理pathlib.Pathnode:path
文件读写openpathlibnode:fs
JSONjsonJSON
时间日期datetimeDate
随机数randomMath.random()
哈希hashlibnode:crypto
命令行参数argparseprocess.argv / commander
正则reRegExp
HTTP 请求urllib / httpx / requestsfetch / axios

18.1 JSON

import json

data = {"name": "Alice", "age": 18}
text = json.dumps(data, ensure_ascii=False)  # '{"name": "Alice", "age": 18}'
obj = json.loads(text)  # {"name": "Alice", "age": 18}
const data = { name: "Alice", age: 18 };
const text = JSON.stringify(data); // '{"name":"Alice","age":18}'
const obj = JSON.parse(text); // { name: "Alice", age: 18 }

18.2 路径

from pathlib import Path

path = Path("data") / "users.json"
print(path.exists())
import path from "node:path";
import fs from "node:fs";

const filePath = path.join("data", "users.json");
console.log(fs.existsSync(filePath));

18.3 日期时间

from datetime import datetime

now = datetime.now()
print(now.strftime("%Y-%m-%d %H:%M:%S"))
const now = new Date();
console.log(now.toISOString());

19. 最小工程化

19.1 创建虚拟环境

python -m venv .venv

Windows 激活:

.venv\Scripts\activate

macOS / Linux 激活:

source .venv/bin/activate

TS 对照心智:

  • 类似给项目准备独立的 node_modules 环境,只不过 Python 更强调解释器和依赖一起隔离。

19.2 安装依赖

pip install requests pytest ruff black

TS 对照:

npm install axios
npm install -D vitest eslint prettier typescript

19.3 推荐目录结构

project/
  app/
    __init__.py
    main.py
    utils.py
  tests/
    test_utils.py
  requirements.txt
  README.md

TS 对照:

project/
  src/
    main.ts
    utils.ts
  tests/
    utils.test.ts
  package.json
  tsconfig.json
  README.md

19.4 测试

tests/test_utils.py

from app.utils import add

def test_add():
    assert add(1, 2) == 3

运行:

pytest

TS 对照:

import { describe, expect, it } from "vitest";
import { add } from "../src/utils";

describe("add", () => {
  it("adds numbers", () => {
    expect(add(1, 2)).toBe(3);
  });
});

19.5 格式化与检查

ruff check .
black .

TS 对照:

eslint .
prettier --write .

19.6 调试

Python 常见方式:

  • print()
  • IDE 断点
  • pdb
import pdb

value = {"name": "Alice"}
pdb.set_trace()
print(value["name"])

TS 对照:

  • console.log()
  • 浏览器 DevTools / VS Code 断点
  • Node inspector

第二部分:TypeScript -> Python 对照速查

20. 核心映射总表

前端/TS 概念Python 对应备注
let直接赋值 x = ...无声明关键字
const约定常量全大写无真正只读变量
nullNone推荐 is None
Arraylist有序可变
元组类型tuple不可变序列
普通对象dict键值映射,不等于 JS 对象
Setset无序去重
for...offor x in xs遍历可迭代对象
for...in常用 for key in dict语义不同
模板字符串f"..."插值很常用
解构解包a, b = pair
展开运算符* / **序列与字典分开
箭头函数lambda仅单表达式
Promise.allasyncio.gather都用于并发等待
try/catchtry/except异常类型更细
classclass方法首参显式 self
Node 模块Python 模块/包导入规则不同

21. 常见一眼就容易写错的点

21.1 真值判断

if not items:
    print("empty")
if (!items.length) {
  console.log("empty");
}

说明:

  • Python 里空列表、空字典、空字符串、0None 都是假值。

21.2 判断空值

if user is None:
    print("no user")
if (user === null) {
  console.log("no user");
}

21.3 深浅拷贝

import copy

state = {"items": [1, 2]}
shallow = state.copy()         # 浅拷贝,内部列表仍可能共享引用
deep = copy.deepcopy(state)    # 深拷贝,内部列表也会被复制
const state = { items: [1, 2] };
const shallow = { ...state }; // 浅拷贝,内部数组仍可能共享引用
const deep = structuredClone(state); // 深拷贝,内部数组也会被复制

21.4 排序

users = [{"age": 20}, {"age": 18}]
sorted_users = sorted(users, key=lambda x: x["age"])  # [{"age": 18}, {"age": 20}]
const users = [{ age: 20 }, { age: 18 }];
const sortedUsers = [...users].sort((a, b) => a.age - b.age); // [{ age: 18 }, { age: 20 }]

21.5 安全取值

city = user.get("city", "unknown")  # 如果 city 不存在,则为 "unknown"
const city = user.city ?? "unknown"; // 如果 user.city 是 null/undefined,则为 "unknown"

22. 从前端思维切到 Python 的建议

  1. 不要先找“完全一模一样的语法”,先找“这段逻辑在 Python 里最自然的写法”。
  2. Python 很多时候更偏向内置能力和标准库,而不是链式 API。
  3. 多使用列表推导式、enumeratezippathlibdataclass 这些 Python 风格工具。
  4. 写 Python 时别太执着“所有东西都对象点点点调用”;很多能力来自语句和内置函数。
  5. 工程化上优先掌握 venvpippytestruff/black,这几样已经足够开始做小项目。

23. 一个完整的最小示例

Python 版本

from dataclasses import dataclass

@dataclass
class Todo:
    title: str
    done: bool = False

def finish(todo: Todo) -> Todo:
    return Todo(title=todo.title, done=True)

def main():
    todos = [Todo("learn python"), Todo("write script")]
    done_titles = [finish(todo).title for todo in todos if not todo.done]
    print(done_titles)

if __name__ == "__main__":
    main()

TypeScript 版本

type Todo = {
  title: string;
  done?: boolean;
};

function finish(todo: Todo): Todo {
  return { ...todo, done: true };
}

function main() {
  const todos: Todo[] = [{ title: "learn python" }, { title: "write script" }];
  const doneTitles = todos.filter(todo => !todo.done).map(todo => finish(todo).title);
  console.log(doneTitles);
}

main();

24. 记忆口诀

  • list 像数组,但更依赖推导式和内置函数。
  • dict 像对象,但别把它当成对象字面量的完全复制。
  • for x in xsfor...of,不是 JS 的 for...in
  • Nonenull,判断时优先 is None
  • Python 没有 const,名字绑定和对象可变性要分开理解。
  • asyncio 像 Promise 世界,但 API 体系是 Python 自己的。
0

评论区