以 JavaScript / TypeScript 为参照,“重学”并“精通” Python。
这篇回到更底层的语言零件:
变量、字符串、列表、元组、字典、条件和循环。
变量、字符串、数字、注释
变量就是名字贴到对象上
Python 没有 const / let / var。写成:
name = "hello world"
count = 1对照 TS:
let name = "hello world"
let count = 1
a = b通常是让两个名字指向同一个对象,不是自动深拷贝一份。
字符串:最常用的是 f-string
first_name = "ada"
last_name = "lovelace"
full_name = f"{first_name} {last_name}"
print(full_name) # ada lovelace对照 JS 模板字符串:
const fullName = `${firstName} ${lastName}`
f就是format
大小写转换也常见:
name = "hello world"
name.title() # Hello World
name.upper() # HELLO WORLD
name.lower() # hello world去空白、去前后缀:
" python ".strip() # "python"
"https://www.baidu.com".removeprefix("https://") # "www.baidu.com"
"https://www.baidu.com".removesuffix(".com") # "https://www.baidu"换行和制表:
print("Languages:\n\tPython\n\tC\n\tJavaScript")\n 换行,\t 缩进。和 JS 一样。
数字:下划线只是给人看的
large_num = 14_000_000_000
print(large_num) # 14000000000下划线不改变数值,只是方便读大数。和 JS 的 14_000_000_000 一样。
多变量一起赋值:
x, y, z = 0, 0, 0“常量”只是约定
MAX_NUM = 1000Python 没有常量关键字。全大写只是告诉人:别改这个。 但运行时照样能改,只是不该改。
注释和文档字符串
单行:
# 这是注释多行常见两种:
"""
多行说明
"""函数里的三引号,常常当文档字符串用:
def greet(name: str) -> str:
"""打招呼,返回问候语。"""
return f"Hello, {name}!"对照:
- JS 的
//、/* */ - TS / JSDoc 的函数说明
Python 更常把说明写进函数体开头的三引号里,工具和帮助信息会读它。
列表:可变数组
基本操作
arr = [1, 2, 3, 4, 5]
len(arr) # 5
arr[2] = 30 # 改第 3 个
arr.append(6) # 末尾追加
arr.insert(2, 7) # 在索引 2 插入
arr.pop() # 弹出最后一个
arr.pop(0) # 弹出索引 0
arr.remove(2) # 按值删第一个匹配项
del arr[2] # 按索引删对照 JS:
| 你想做的事 | JavaScript | Python |
|---|---|---|
| 长度 | arr.length | len(arr) |
| 末尾追加 | arr.push(x) | arr.append(x) |
| 弹出末尾 | arr.pop() | arr.pop() |
| 按索引删 | arr.splice(i, 1) | del arr[i] / arr.pop(i) |
| 按值删 | 自己找 index 再 splice | arr.remove(x) |
| 中间插入 | arr.splice(i, 0, x) | arr.insert(i, x) |
一句话:
Python 的
list,就是你脑子里的可变数组。
名字不叫 array,行为很像 JS 的 Array
拼接:
arr3 = arr + [9, 10, 11]排序和反转
arr.sort() # 原地升序
arr.sort(reverse=True) # 原地降序
sorted(arr) # 返回新列表,不改原列表
arr.reverse() # 原地反转要记住一对:
arr.sort():改自己,返回Nonesorted(arr):不改自己,返回新列表
JS 也有类似坑:
arr.sort()会改原数组;需要新数组时用[...arr].sort()或toSorted()。
遍历、range、统计
for i in arr:
print(i)
for i in range(0, 10):
print(i) # 0 到 9,不含 10
list(range(0, 10)) # [0, 1, 2, ..., 9]
max(arr)
min(arr)
sum(arr)range(0, 10) 很像:
for (let i = 0; i < 10; i++) {}只是 Python 的终点默认不含右边界。
列表推导式:Python 的高频写法
squares = [value ** 2 for value in range(1, 11)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]对照 JS:
const squares = Array.from({ length: 10 }, (_, i) => (i + 1) ** 2)
// 或
const squares = [...Array(10)].map((_, i) => (i + 1) ** 2)读法:
先写
最终要留下的值,再写for ... in ...。
它是 Python 里非常常见的“边遍历边生成新列表”写法。
切片:取出一段,也常用来复制
arr = [0, 1, 2, 3, 4]
arr[0:2] # [0, 1],含左不含右
arr[:2] # 从头到索引 2(不含)
arr[2:] # 从索引 2 到结尾对照 JS 的 slice:
arr.slice(0, 2)
arr.slice(0, 2)
arr.slice(2)复制列表:[:] 和直接赋值不是一回事
arr1 = arr[:] # 浅拷贝,新列表
arr2 = arr # 同一个列表,两个名字对照 JS:
const arr1 = arr.slice() // 或 [...arr]
const arr2 = arr // 同一引用这里接回开头那句:
arr2 = arr不是复制内容,只是再贴一张标签。
改arr2,arr也会变。
元组:写完就不能改的列表
dimension = (200, 50)
print(dimension[0]) # 200
for i in dimension:
print(i)- 用圆括号
- 元素不能改、不能增删
- 能遍历、能按索引读
对照 TS:
const dimension = [200, 50] as const
// 或
const dimension: readonly [number, number] = [200, 50]一句话:
list是可变盒子;tuple是装好就封条的盒子。
配置、坐标、不会改的一组值,常用元组。
只有一个元素时要写逗号:
# 必须要要写逗号
one = (1,) # 元组
# 没有逗号就是数字 1
not_tuple = (1) # 只是括号里的数字 1条件判断、布尔、逻辑
if score >= 90:
grade = "A"
elif score >= 60:
grade = "B"
else:
grade = "C"对照 JS:
if (score >= 90) {
grade = "A"
} else if (score >= 60) {
grade = "B"
} else {
grade = "C"
}关键差别:
| 点 | JavaScript | Python |
|---|---|---|
| 否则如果 | else if | elif |
| 逻辑与 / 或 / 非 | && || ! | and or not |
| 块边界 | {} | : + 缩进 |
| 真假字面量 | true / false | True / False |
比较运算符两边都懂:==、!=、>、<、>=、<=。
布尔值首字母大写:
ok = True
empty = FalsePython 也有“真值”习惯:
items = []
if items: # 空列表为假
...
if not items: # 没有元素
...空列表、空字典、空字符串、0、None 在条件里都偏“假”。
这和 JS 的 truthy / falsy 很像,但具体集合不完全相同;写业务时,能显式判断就显式判断。
字典:像对象,也像 Map
favorite = {
"name": "zhangsan",
"age": 18,
}对照 JS:
const favorite = {
name: "zhangsan",
age: 18,
}读取、修改、删除:
favorite["name"]
favorite["age"] = 19
# del
del favorite["age"]遍历时,Python 比 JS 对象更常把键值拆开写:
for key, value in favorite.items():
print(key, value)
for key in favorite.keys():
print(key)
for value in favorite.values():
print(value)对照:
for (const [key, value] of Object.entries(favorite)) {}
for (const key of Object.keys(favorite)) {}
for (const value of Object.values(favorite)) {}一句话:
Python 的
dict,就是“键到值”的映射。
在 FastAPI / JSON 场景里,它几乎就是你脑子里的普通对象;只是键不一定是字符串,值可以是任意对象。
字典可以嵌套:
payload = {
"user": {"id": 1, "name": "ada"},
"tags": ["python", "fastapi"],
}这正是后面 Pydantic Model、请求体、响应 JSON 的日常形状。
取值时两个常见写法:
favorite["name"] # 没有 key 会报 KeyError
favorite.get("name") # 没有 key 返回 None
favorite.get("name", "") # 没有 key 返回默认值对照 JS:
favorite.name
favorite.name ?? ""用户输入:本地脚本才常用
message = input("请输入内容:")
print("你输入的是:", message)input() 返回的永远是字符串。要当数字用,自己转:
age = int(input("年龄:"))在 FastAPI 服务里,参数通常来自 Path / Query / Body,很少直接用 input()。
它属于本地脚本、命令行小工具的基础零件;
while 循环
基本形态
n = 1
while n <= 5:
print(n)
n += 1对照 JS:
let n = 1
while (n <= 5) {
console.log(n)
n += 1
}break 跳出,continue 跳过本轮,两边都一样。
注意 continue 时别忘了推进循环变量,否则容易死循环:
j = 1
while j <= 5:
if j == 3:
j += 1
continue
print(j)
j += 1while arr::直到清空
arr = [1, 2, 3, 4, 5]
while arr:
cur = arr.pop()
print(cur)
# 5 4 3 2 1这是利用“空列表为假”的写法:有元素就继续,弹完为止。
处理队列、消化待办列表时很常见。
- 多数 Web 接口代码更常写
for; while留给“不知道要转几圈,但知道停条件”的场景。
一张总对照表
| 概念 | JavaScript / TypeScript | Python |
|---|---|---|
| 变量 | let / const | 直接 name = ... |
| 字符串插值 | `${x}` | f"{x}" |
| 数组 | Array | list |
| 不可变一组值 | as const / readonly tuple | tuple |
| 对象映射 | object / Map | dict |
| 长度 | .length | len(x) |
| 否则如果 | else if | elif |
| 逻辑运算 | && || ! | and or not |
| 真假 | true / false | True / False |
| 代码块 | {} | : + 缩进 |
| 生成新列表 | map / filter | 列表推导式 |
| 切片 | slice | arr[a:b] |
| 同引用赋值 | b = a | b = a |
| 浅拷贝数组 | [...a] / a.slice() | a[:] |
补充
注释与文档字符串
- Python 的注释只有
#; - 三引号创建字符串,放在模块、类或函数开头时才是
文档字符串。
# 这是注释
text = """这是多行字符串"""
# 函数体开头的三引号字符串是文档字符串
def greet():
"""这是函数的文档字符串。"""== 与 is
== 比较值,is 比较是否为同一个对象;is 最常用于 is None。
a = [1]
b = [1]
c = a
# 值相同,所以是 True
print(a == b)
# 不是同一个对象,所以是 False
print(a is b)
# 是同一个对象,所以是 True
print(a is c)
value = None
# value 就是 None,所以是 True
print(value is None)原地修改与返回值
list、dict 可变,原地修改方法通常返回 None;str 不可变,字符串方法返回新字符串。
items = [3, 1]
result = items.sort()
# 原列表已经变成 [1, 3]
print(items)
# sort() 原地修改列表,返回 None
print(result)
name = "python"
# 返回新字符串 PYTHON
print(name.upper())
# 原字符串仍然是 python
print(name)不要写 items = items.append(x),否则 items 会变成 None。
浅拷贝与元组
[:] 只复制外层;元组的元素不能替换,但元组里的可变对象仍然能改。
original = [{"done": False}]
copied = original[:]
copied[0]["done"] = True
# 内层字典仍然共享,所以原列表中的值也是 True
print(original[0]["done"])
task = ("学习", [])
task[1].append("Python")
# 元组中的列表可以修改
print(task)
# 下面会报 TypeError,因为不能替换元组元素
# task[1] = []需要递归复制嵌套对象时,再用 copy.deepcopy()。
假值与字典
0、空字符串、空容器和 None 都是假值;判断“没传”用 is None。
limit = 0
# 0 是假值
print(bool(limit))
payload = {"name": None}
# 键存在,值是 None
print(payload.get("name"))
# 键不存在,也返回 None
print(payload.get("age"))
# name 键存在
print("name" in payload)
# age 键不存在
print("age" in payload)Python 的空列表、空字典是假值,JS 中则是真值。字典键必须可哈希,list、dict 不能做键。