知识点思维导图
29 个知识节点
参考资料
Python(03) - Python 与 JavaScript 对比
读完后,你应能完成以下任务:
- 绘制“Python(03) - Python 与 JavaScript 对比 / 核心思路”的关键对象与数据流,解释“和你从 JS 转 Java 不同:Java 是"强类型 + 编译检查",处处和 JS 别扭;”,并用源码位置、日志或 Trace 标注证据。
- 为“Python(03) - Python 与 JavaScript 对比 / 变量和类型”设计正常与异常输入,验证“True / False / None 首字母大写。 -> int 和 float 是分开的两种类型(JS 只有一个 number)。 -> 没有 undefined,空值只有 None 一个。”,输出首个偏差位置与回归测试结果。
- 实现“Python(03) - Python 与 JavaScript 对比 / 变量声明”的最小代码或配置,检验“全大写 AGE 只是约定告诉别人"别改我",语言层面照样能改。”,输出命令、结果与 Diff,并说明不适用边界。
你已经会 JS/TS,本篇用一张对照表帮你把 Python 的变量、函数、类型、常用操作一次性对上号。重点不是"记语法",而是划清那些长得像但行为不一样的坑(比如
self不是this、is不是===)。
一、核心思路
Python ≈ 动态类型的 JS(像不写类型的 JavaScript),但用缩进代替 {}、用换行代替 ;。
和你从 JS 转 Java 不同:Java 是"强类型 + 编译检查",处处和 JS 别扭;而 Python 的类型系统和 JS 几乎一样松(运行时才检查),所以上手比 Java 顺。真正的差异集中在三处:写法(缩进/命名)、几个同名不同义的关键字、以及 self 这个最大的陷阱。
边界提醒:本篇只讲语法对照,建立"我大概会写了"的直觉。像
async不受 GIL 影响、装饰器机制、生成器原理这些,留到对应专题篇深入。
二、变量和类型
2.1 变量声明
| JavaScript | TypeScript | Python |
|---|---|---|
let name = "Tom" |
let name: string = "Tom" |
name = "Tom" |
const AGE = 18 |
const AGE: number = 18 |
AGE = 18(约定大写表示常量) |
关键差异(边界):
- 没有
let/const/var,直接变量名 = 值。 - Python 没有真正的常量。全大写
AGE只是约定告诉别人"别改我",语言层面照样能改。这点和 JS 的const(真正只读)不一样,别套用。 - 行尾不写分号
;(写了也不报错,但不符合习惯)。 - 命名习惯是
snake_case(下划线),不是 JS 的camelCase。这是社区强约定,建议入乡随俗。
2.2 类型提示(Type Hints)≈ TS 的类型注解
Python 默认动态类型,但可选地写类型提示,写法和 TS 几乎一样(都是"变量名在前、类型在后"):
// TypeScript:类型是强制检查的
let count: number = 10;
let userName: string = "Tom";
边界:TS 的类型在编译期会报错;Python 的类型提示运行时完全不检查,写错类型照样跑。它的价值是给 IDE 补全和 mypy 这类静态检查工具用。后面学 FastAPI / Pydantic 时,类型提示会"变成真的"(被框架拿去做校验),到那篇再展开。
2.3 基本类型对照
| JS/TS | Python | 说明 |
|---|---|---|
number |
int |
整数 |
number |
float |
小数(浮点) |
string |
str |
字符串 |
boolean |
bool |
布尔值,True / False 首字母大写 |
null / undefined |
None |
空值,只有一个 None,首字母大写 |
Array |
list |
列表 |
object / Map |
dict |
字典 |
[a, b](TS 元组类型,但默认可改) |
tuple |
元组(真正不可变) |
Set |
set |
集合 |
最容易踩的三个坑:
True/False/None首字母大写。写成 JS 的true/null会直接报NameError。int和float是分开的两种类型(JS 只有一个number)。10是 int,10.0是 float。- 没有
undefined,空值只有None一个。
// JavaScript
let isActive = true;
let data = null;
三、函数
3.1 声明格式
| JavaScript | Python |
|---|---|
function add(a, b) { return a + b } |
def add(a, b): return a + b |
箭头函数 (a, b) => a + b |
lambda a, b: a + b |
Python 格式:
3.2 完整例子(并排对照)
// JavaScript
function greet(name) {
return "Hello, " + name;
}
带类型提示的版本(≈ TS):
3.3 默认参数 & 关键字参数(比 JS 强大)
JS 的默认参数你已经会。Python 额外支持调用时按名字传参,可读性很高:
// JavaScript:默认参数
function createUser(name, age = 18) { ... }
createUser("Tom"); // 只能按位置传
坑:默认参数不要用可变对象(如
def f(items=[]))。因为默认值只在定义时创建一次,多次调用会共享同一个 list,导致诡异 bug。需要时用def f(items=None): items = items or []。这是 Python 新手的经典陷阱。
3.4 程序入口:没有 main,但有 if name == "main"
Python 没有 Java 那种强制的 main 方法。文件从上到下直接执行。但有个固定写法用来区分"被直接运行"还是"被 import":
类比:有点像 Node 里判断 if (require.main === module)——只在直接运行时跑入口逻辑。
四、列表、字典与常用操作
4.1 列表 list ≈ JS Array
list 就是 JS 的 Array,但方法名变了:
// JavaScript
let arr = [1, 2, 3];
arr.push(4); // 末尾追加
arr.length; // 长度
arr[0]; // 取第一个
arr.includes(2); // 是否包含
| JS | Python |
|---|---|
arr.push(x) |
arr.append(x) |
arr.length |
len(arr) |
arr[i] |
arr[i] |
arr.includes(x) |
x in arr |
arr.slice(1, 3) |
arr[1:3](切片语法) |
arr[arr.length - 1] |
arr[-1](负索引取倒数,JS 没有) |
亮点:Python 的切片很强。
arr[1:3]取索引 1~2,arr[-1]取最后一个,arr[::-1]直接反转。这是 JS 没有的语法糖。
4.2 字典 dict ≈ JS object / Map
// JavaScript
let map = {};
map["age"] = 18; // 或 map.age = 18
map["age"]; // 取值
delete map["age"]; // 删除
"age" in map; // 是否有 key
| JS | Python |
|---|---|
obj[key] = value |
d[key] = value |
obj[key] |
d[key] |
obj.key(点语法) |
❌ 不支持,只能用 d[key] |
obj[key] ?? default |
d.get(key, default) |
delete obj[key] |
del d[key] |
Object.keys(obj) |
d.keys() |
坑:字典取不存在的 key 会抛
KeyError异常,不像 JS 返回undefined。不确定 key 在不在时,用d.get(key)(默认返回 None)或d.get(key, 默认值)。
4.3 列表推导式 ≈ map / filter 的浓缩写法
JS 里 arr.map(...).filter(...) 链式调用,Python 有更紧凑的列表推导式:
// JavaScript
let nums = [1, 2, 3, 4];
let doubled = nums.map(n => n * 2); // 每个翻倍
let evens = nums.filter(n => n % 2 === 0); // 只留偶数
读法:"结果表达式 for 元素 in 集合 if 条件"。一开始别扭,写几次就顺了,这是 Python 最常用的写法之一。
五、类和对象(最大的坑:self)
5.1 类定义
// TypeScript
class User {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet(): string {
return `Hello, ${this.name}`;
}
}
const u = new User("Tom", 18);
关键差异(重点边界):
self不是this。this是 JS 隐式给的,Python 的self必须手动写成方法的第一个参数,并且调用时不用传(解释器自动塞进去)。这是前端转 Python 最高频的报错来源。- 构造方法固定叫
__init__,不是constructor。 - 创建对象不用
new,直接User("Tom", 18)。 - 访问成员一律
self.xxx,漏写self.会被当成局部变量。
为什么 self 要显式写?(WHY) Python 的设计哲学是"显式优于隐式"——方法本质上就是个普通函数,
u.greet()等价于User.greet(u),那个u就是传给self的。理解了这一层,self 就不神秘了。
5.2 f-string(模板字符串)
// JavaScript:反引号 + ${}
let msg = `Hello, ${name}, you are ${age}`;
一对一映射,把反引号换成 f"..."、去掉 $ 即可。
六、控制流(和 JS 像,但有几个坑)
6.1 条件判断
| JS | Python | 说明 |
|---|---|---|
else if |
elif |
拼写不同 |
&& || ! |
and or not |
用英文单词,不是符号 |
=== |
== |
Python 没有 ===,== 比的是值 |
a ? b : c |
b if a else c |
三元语序反了,结果在前 |
// JavaScript 三元
let result = age >= 18 ? "成年" : "未成年";
6.2 循环
坑:Python 没有
++/--自增运算符。要写count += 1/count -= 1。
七、相等判断与真值(高频坑)
7.1 == vs is
is 不是 JS 的 ===! 别被长度迷惑。规则:
- 比值用
==(这是日常默认选择)。 is只用在判断None:写if x is None:,这是社区规范(不写x == None)。
// JavaScript
if (data === null) { ... }
7.2 真值(Truthy / Falsy)
和 JS 类似但更直觉:空列表 []、空字典 {}、空字符串 ""、0、None 都是假值。
八、模块与包(≈ import / npm)
8.1 导入导出
Python 没有 export——一个文件(模块)里定义的所有东西默认都能被别的文件导入。
// JavaScript
import { add } from './utils';
import axios from 'axios';
| JS | Python |
|---|---|
import { x } from './m' |
from m import x |
import * as m from './m' |
import m(用 m.x 调用) |
export function x |
无需导出,定义即可被导入 |
npm install axios |
pip install requests |
package.json |
requirements.txt / pyproject.toml |
node_modules/ |
虚拟环境 venv/(见环境配置篇) |
边界:JS 的依赖装在项目本地
node_modules;Python 默认装到全局,所以才需要虚拟环境隔离不同项目(环境篇已讲)。心智上pip≈npm,venv≈ 项目级隔离。
九、常见语法速查表
| 功能 | JavaScript/TypeScript | Python |
|---|---|---|
| 变量 | let x = 1 |
x = 1 |
| 常量 | const X = 1 |
X = 1(仅约定大写) |
| 代码块 | { ... } |
缩进(4 个空格) |
| 行尾 | ; |
直接换行 |
| 命名 | camelCase |
snake_case |
| 字符串模板 | `Hi ${name}` |
f"Hi {name}" |
| 函数 | function f(x) {} |
def f(x): |
| 箭头函数 | (x) => x + 1 |
lambda x: x + 1 |
| 空值 | null / undefined |
None |
| 布尔 | true / false |
True / False |
| 逻辑与或非 | && || ! |
and or not |
| 相等 | === |
==(判空用 is None) |
| 三元 | a ? b : c |
b if a else c |
| 列表追加 | arr.push(x) |
arr.append(x) |
| 长度 | arr.length |
len(arr) |
| 字典取值 | obj[k] / obj[k] ?? d |
d[k] / d.get(k, 默认) |
| 包含判断 | arr.includes(x) |
x in arr |
| 遍历 | for (const x of arr) |
for x in arr: |
| 带索引遍历 | arr.entries() |
enumerate(arr) |
| 自增 | i++ |
i += 1(无 ++) |
| this | this |
self(需显式声明) |
| 构造器 | constructor() |
def __init__(self) |
| 实例化 | new User() |
User()(无 new) |
| 输出 | console.log(x) |
print(x) |
| 注释 | // /* */ |
# """ """ |
十、总结
- 核心思路:和你从 JS 转 Java 不同:Java 是"强类型 + 编译检查",处处和 JS 别扭;
- 变量和类型:True / False / None 首字母大写。 -> int 和 float 是分开的两种类型(JS 只有一个 number)。 -> 没有 undefined,空值只有 None 一个。
- 函数:因为默认值只在定义时创建一次,多次调用会共享同一个 list,导致诡异 bug。
- 类和对象(最大的坑:self):self 不是 this。 -> 构造方法固定叫 init,不是 constructor。 -> 创建对象不用 new,直接 User("Tom", 18)。 -> 访问成员一律 self.xxx,漏写 self. 会被当成局部变量。
- 控制流(和 JS 像,但有几个坑):| && || ! | and or not | 用英文单词,不是符号 |
- 模块与包(≈ import / npm):边界:JS 的依赖装在项目本地 node_modules;
学完自测
选择所有正确答案;提交后逐项核对判断依据。