Week 1:Python 语法速成(TypeScript 对照)
🎯 本周目标:花 10-12 小时,搞定 Python 基础语法。重点学「和 TypeScript 的差异」,而不是从头死记。
1. 环境准备
安装 Python
推荐版本 3.11+(你项目的 pyproject.toml 要求的版本)。
Windows 用户:去 python.org 下载安装包,安装时勾选 "Add Python to PATH"。
创建虚拟环境(对应 npm/node_modules)
# 创建 .venv 目录(相当于 node_modules 的隔离环境)
python -m venv .venv
# 激活虚拟环境
.venv\Scripts\Activate.ps1
# 退出虚拟环境
deactivate
💡 TS 对照:虚拟环境 =
node_modules隔离机制。Python 没有像 npm workspaces 那样的 monorepo 管理工具,但.venv足够用了。
pip 包管理
# 安装包(相当于 npm install / pnpm add)
.venv\Scripts\python -m pip install fastapi
# 查看已安装的包
.venv\Scripts\python -m pip list
# 导出依赖(相当于 package.json)
.venv\Scripts\python -m pip freeze > requirements.txt
2. 核心语法对照表(贴在显示器上!)
变量和类型
# ===== Python =====
x: str = "hello" # 显式类型(和 TS 一样)
y = 42 # 类型推断(和 TS 一样!)
z = 3.14 # float
is_ok = True # bool,注意大写 T!
items: list[int] = [1, 2, 3]
config: dict[str, any] = {"key": "value"}
# ===== TypeScript 对照 =====
// const x: string = "hello"
// const y = 42
// const z = 3.14
// const isOk = true
// const items: number[] = [1, 2, 3]
// const config: Record<string, any> = { key: "value" }
⚠️ 注意点
- Python 用
snake_case(函数名、变量名),TS 用camelCase - Python 的
bool值是True/False(大写开头),TS 是true/false - Python 没有
const!所有变量默认都是可变的(用全大写MAX_SIZE表示常量只是约定)
字符串
name = "Alice"
age = 25
# f-string = TS 的模板字符串 `${}`
greeting = f"Hello, {name}! You are {age} years old."
# 多行字符串(用三引号,和 JS 的模板字符串一样)
desc = """
这是一个
多行文本
"""
# ===== TS 对照 =====
// const greeting = `Hello, ${name}! You are ${age} years old.`
// const desc = `这是一个
// 多行文本`;
条件和循环
# ===== if/elif/else =====
score = 85
if score >= 90:
grade = "A"
elif score >= 60: # 注意是 elif,不是 else if
grade = "B"
else:
grade = "C"
# ===== for 循环 =====
fruits = ["apple", "banana", "cherry"]
for fruit in fruits: # 相当于 TS 的 for...of
print(f"水果: {fruit}")
# 带索引的遍历
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
# ===== while 循环 =====
count = 0
while count < 5:
count += 1
print(count)
# ===== TS 对照 =====
// fruits.forEach((fruit, i) => console.log(`${i}: ${fruit}`))
// for (const fruit of fruits) { ... }
// while (count < 5) { count++; }
⚠️ 关键差异
- Python 用缩进表示代码块,不用花括号!缩进必须是 4 个空格(不要用 tab)
elif= TS 的else if- 没有
switch语句(Python 3.10+ 有match/case,但很少用)
函数
# ===== 基本函数 =====
def add(a: int, b: int) -> int:
return a + b
# ===== 默认参数 =====
def greet(name: str, greeting: str = "Hello") -> str:
return f"{greeting}, {name}!"
# ===== 关键字参数 =====
result = greet(greeting="Hi", name="World") # 顺序可以换!
# ===== 不定参数 =====
def sum_all(*numbers: int) -> int: # *args 接收多个位置参数
return sum(numbers)
def print_config(**kwargs: any) -> None: # **kwargs 接收多个命名参数
for k, v in kwargs.items():
print(f"{k} = {v}")
# ===== 返回 None =====
def log(msg: str) -> None:
print(msg)
# ===== TS 对照 =====
// function add(a: number, b: number): number { return a + b; }
// function greet(name: string, greeting = "Hello"): string { ... }
类和对象
# ===== dataclass(推荐!相当于 TS 的 interface + 自动构造函数)=====
from dataclasses import dataclass
@dataclass
class Todo:
id: int
text: str
done: bool = False # 默认值
# 使用
t = Todo(id=1, text="买牛奶")
print(t.text) # 买牛奶
print(t) # Todo(id=1, text='买牛奶', done=False) — 自动生成 __repr__
# ===== 传统类写法(了解即可)=====
class Animal:
def __init__(self, name: str): # 构造函数
self.name = name # self = this
def speak(self) -> None:
print(f"{self.name} says...")
class Dog(Animal): # 继承
def speak(self) -> None:
print(f"{self.name} says: Woof!")
# ===== TS 对照 =====
// interface Todo { id: number; text: string; done?: boolean }
// class Animal { constructor(public name: string) {} speak() {} }
// class Dog extends Animal { speak() {} }
💡 推荐用 dataclass
@dataclass 是 Python 3.7+ 引入的,自动生成 __init__、__repr__、__eq__ 等方法,比手写类简洁得多。在 TypeScript 里你用 interface 定义数据结构,在 Python 里就用 @dataclass。
导入
# ===== 标准库导入 =====
import math # 整个模块
from datetime import datetime # 只导入某个函数/类
from os import path as ospath # 重命名
# ===== 第三方库导入(安装后)=====
from fastapi import FastAPI
from pydantic import BaseModel
# ===== 本地模块导入 =====
from my_package.my_module import my_func
# ===== TS 对照 =====
// import * as math from 'math'
// import { FastAPI } from 'fastapi'
// import { myFunc } from './my-module'
3. 练手:Todo CLI(TS → Python 翻译练习)
把下面这段 TypeScript 翻译成 Python。先自己写,再看答案。
// ===== Todo.ts (TypeScript 原始版本) =====
interface Todo {
id: number;
text: string;
done: boolean;
}
const todos: Todo[] = [];
let nextId = 1;
function addTodo(text: string): void {
todos.push({ id: nextId++, text, done: false });
console.log(`✅ Added: ${text}`);
}
function listTodos(): void {
todos.forEach((t) => {
const status = t.done ? '✓' : '○';
console.log(`${status} ${t.id}. ${t.text}`);
});
}
function toggleTodo(id: number): void {
const todo = todos.find((t) => t.id === id);
if (todo) {
todo.done = !todo.done;
}
}
// 测试
addTodo("学习 Python");
addTodo("写 FastAPI demo");
listTodos();
toggleTodo(1);
listTodos();
Python 参考答案(带注释)
# ===== todo.py =====
from dataclasses import dataclass # 相当于 TS 的 interface
@dataclass
class Todo:
id: int
text: str
done: bool = False
todos: list[Todo] = [] # 相当于 const todos: Todo[] = []
next_id: int = 1 # snake_case 是 Python 规范
def add_todo(text: str) -> None:
global next_id # Python 需要声明才能修改全局变量
todos.append(Todo(id=next_id, text=text)) # 不用 new 关键字!
next_id += 1
print(f"✅ Added: {text}") # f-string = 模板字符串
def list_todos() -> None:
for t in todos: # for...of 循环
status = '✓' if t.done else '○' # 三元运算符
print(f"{status} {t.id}. {t.text}")
def toggle_todo(id: int) -> None:
for todo in todos: # 相当于 Array.find()
if todo.id == id:
todo.done = not todo.done # not = !
break
# 测试
add_todo("学习 Python")
add_todo("写 FastAPI demo")
list_todos()
toggle_todo(1)
list_todos()
运行方式
.venv\Scripts\python todo.py
预期输出
✅ Added: 学习 Python
✅ Added: 写 FastAPI demo
○ 1. 学习 Python
○ 2. 写 FastAPI demo
✓ 1. 学习 Python
○ 2. 写 FastAPI demo
4. 本周作业
| # | 任务 | 验收标准 |
|---|---|---|
| 1 | 把上面的 Todo CLI 用 Python 实现一遍 | 运行输出和预期一致 |
| 2 | 给 Todo CLI 加一个 delete_todo(id: int) 函数 | 能正确删除 |
| 3 | 给 Todo 加一个 priority 字段(1-5),按优先级排序显示 | list_todos 按 priority 降序 |
| 4 | 把数据持久化到 JSON 文件 | 重启后数据不丢 |
| 5 | 读《Python Crash Course》前 10 章(可选,辅助) | 理解基础语法 |
5. 避坑速查
| 坑 | 原因 | 解决 |
|---|---|---|
IndentationError | 混用 tab 和空格 | VS Code 设置 editor.insertSpaces: true |
NameError: name 'xxx' is not defined | Python 没有变量提升,且作用域更严格 | 确保变量在使用前已赋值 |
| 修改全局变量报错 | 函数内需要声明 global 或 nonlocal | 尽量不要用全局变量,传参更好 |
bool 拼写错误 | Python 是 True/False(大写开头) | 记! |
| 忘记加冒号 | def foo(): / if x: / class Foo: | 所有代码块开头必须有冒号 |