
前言
作为一名前端开发工程师,当我决定学习 Python 时,发现网上的教程要么从零开始讲解编程概念,要么直接深入 Python 高级特性,很少有专门为前端开发者设计的学习路径。实际上,我们已经掌握了 JavaScript 的核心编程思想,完全可以通过类比的方式快速掌握 Python。
本文将从前端开发者的视角,系统地对比 JavaScript 和 Python 的差异,帮助你在最短时间内建立起 Python 的知识体系。
一、基础语法对比
1.1 变量声明与赋值
JavaScript 中我们需要使用 let、const 或 var 来声明变量,而 Python 则更加简洁,直接赋值即可。
javascript
// JavaScript
let name = "张三";
const age = 25;
var isStudent = true;
let score = null;
let address; // undefined
python
# Python
name = "张三"
age = 25
is_student = True # 注意:布尔值首字母大写
score = None # Python 中的空值
# Python 中没有 undefined 的概念
关键差异:
- Python 不需要变量声明关键字
- Python 的变量命名推荐使用
snake_case(下划线命名) - Python 只有
None,没有undefined - Python 的布尔值是
True和False,首字母大写
1.2 函数定义
javascript
// JavaScript - 传统函数
function greet(name) {
return `Hello, ${name}!`;
}
// JavaScript - 箭头函数
const add = (a, b) => a + b;
// JavaScript - 默认参数
function createUser(name, age = 18) {
return { name, age };
}
python
# Python - 使用 def 关键字
def greet(name):
return f"Hello, {name}!"
# Python - 单行函数(lambda)
add = lambda a, b: a + b
# Python - 默认参数
def create_user(name, age=18):
return {"name": name, "age": age}
关键差异:
- Python 使用
def关键字定义函数 - Python 使用冒号
:和缩进来定义函数体 - Python 的 lambda 函数功能相对简单,只能写表达式
- Python 的 f-string 类似 JavaScript 的模板字符串
1.3 条件语句
javascript
// JavaScript
if (age >= 18) {
console.log("成年人");
} else if (age >= 13) {
console.log("青少年");
} else {
console.log("儿童");
}
// 三元运算符
const status = age >= 18 ? "成年" : "未成年";
python
# Python
if age >= 18:
print("成年人")
elif age >= 13: # 注意:是 elif 不是 else if
print("青少年")
else:
print("儿童")
# 三元运算符(条件表达式)
status = "成年" if age >= 18 else "未成年"
关键差异:
- Python 使用
elif而不是else if - Python 用缩进代替花括号
- Python 的三元运算符语法顺序不同
1.4 循环语句
javascript
// JavaScript - for 循环
for (let i = 0; i < 5; i++) {
console.log(i);
}
// JavaScript - while 循环
let i = 0;
while (i < 5) {
console.log(i);
i++;
}
// JavaScript - 遍历数组
const fruits = ["apple", "banana", "orange"];
for (let fruit of fruits) {
console.log(fruit);
}
fruits.forEach((fruit, index) => {
console.log(index, fruit);
});
python
# Python - for 循环(使用 range)
for i in range(5):
print(i)
# Python - while 循环
i = 0
while i < 5:
print(i)
i += 1 # Python 没有 i++ 语法
# Python - 遍历列表
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
print(fruit)
# Python - 带索引遍历
for index, fruit in enumerate(fruits):
print(index, fruit)
关键差异:
- Python 使用
range()函数生成数字序列 - Python 没有
i++或i--语法,使用i += 1 - Python 使用
enumerate()同时获取索引和值 - Python 的 for 循环更接近 JavaScript 的
for...of
二、数据类型深度对比
2.1 基本数据类型对比表
| 类型 | JavaScript | Python | 说明 |
|---|---|---|---|
| 字符串 | String |
str |
Python 单引号双引号完全等价 |
| 数字(整数) | Number |
int |
Python 整数无大小限制 |
| 数字(浮点) | Number |
float |
Python 区分整数和浮点数 |
| 布尔值 | Boolean (true/false) |
bool (True/False) |
Python 首字母大写 |
| 空值 | null, undefined |
None |
Python 只有 None |
| 数组/列表 | Array |
list |
Python 称为列表 |
| 对象/字典 | Object |
dict |
Python 称为字典 |
| 集合 | Set |
set |
两者类似 |
| 元组 | 无直接对应 | tuple |
Python 特有的不可变序列 |
2.2 数字类型详解
javascript
// JavaScript - 只有一个 Number 类型
let intNum = 42;
let floatNum = 3.14;
console.log(typeof intNum); // "number"
console.log(typeof floatNum); // "number"
// JavaScript - 数字运算
console.log(5 / 2); // 2.5
console.log(5 // 2); // 语法错误
python
# Python - 区分 int 和 float
int_num = 42
float_num = 3.14
print(type(int_num)) # <class 'int'>
print(type(float_num)) # <class 'float'>
# Python - 数字运算
print(5 / 2) # 2.5 (浮点除法)
print(5 // 2) # 2 (整除)
print(5 ** 2) # 25 (幂运算)
print(5 % 2) # 1 (取模)
# Python - 大整数支持
big_num = 12345678901234567890
print(big_num * 2) # Python 整数无限精度
关键差异:
- Python 明确区分整数和浮点数
- Python 有整除运算符
// - Python 支持幂运算符
** - Python 整数没有大小限制,JavaScript 有
Number.MAX_SAFE_INTEGER
2.3 字符串类型详解
javascript
// JavaScript - 字符串操作
let str = "Hello World";
console.log(str.length); // 11
console.log(str.toUpperCase()); // "HELLO WORLD"
console.log(str.toLowerCase()); // "hello world"
console.log(str.includes("World")); // true
console.log(str.startsWith("Hello")); // true
console.log(str.endsWith("World")); // true
console.log(str.split(" ")); // ["Hello", "World"]
console.log(str.slice(0, 5)); // "Hello"
console.log(str.replace("World", "Python")); // "Hello Python"
// 模板字符串
let name = "张三";
let greeting = `你好, ${name}!`;
python
# Python - 字符串操作
str = "Hello World"
print(len(str)) # 11 (使用 len 函数)
print(str.upper()) # "HELLO WORLD"
print(str.lower()) # "hello world"
print("World" in str) # True (使用 in 关键字)
print(str.startswith("Hello")) # True
print(str.endswith("World")) # True
print(str.split(" ")) # ["Hello", "World"]
print(str[0:5]) # "Hello" (使用切片)
print(str.replace("World", "Python")) # "Hello Python"
# f-string (Python 3.6+)
name = "张三"
greeting = f"你好, {name}!"
# 多行字符串
multi_line = """
这是第一行
这是第二行
这是第三行
"""
关键差异:
- Python 使用
len()函数获取长度,不是.length属性 - Python 使用
in关键字检查子字符串 - Python 使用切片语法
[start:end]而不是slice()方法 - Python 支持三引号创建多行字符串
- Python 字符串是不可变的(这点与 JavaScript 相同)
2.4 类型转换
javascript
// JavaScript - 类型转换
String(123); // "123"
Number("123"); // 123
Boolean(1); // true
parseInt("123"); // 123
parseFloat("3.14"); // 3.14
// JavaScript - 隐式转换
"5" + 3; // "53" (字符串拼接)
"5" - 3; // 2 (数字运算)
"5" * "2"; // 10
python
# Python - 类型转换
str(123) # "123"
int("123") # 123
float("3.14") # 3.14
bool(1) # True
# Python - 严格的类型系统
"5" + 3 # TypeError: 类型错误
"5" + str(3) # "53"
int("5") + 3 # 8
# Python - 真值转换
bool(0) # False
bool("") # False
bool([]) # False
bool({}) # False
bool(None) # False
bool("False") # True (非空字符串都是 True)
关键差异:
- Python 的类型转换更严格,不会自动进行隐式转换
- Python 的真值判断更直观
- Python 不允许字符串和数字直接相加
三、数组与列表方法对比
3.1 创建与访问
javascript
// JavaScript - 数组创建
const arr1 = [1, 2, 3, 4, 5];
const arr2 = new Array(5); // 创建长度为 5 的数组
const arr3 = Array.from({length: 5}, (v, i) => i);
// 访问元素
console.log(arr1[0]); // 1
console.log(arr1[arr1.length - 1]); // 5
console.log(arr1[-1]); // undefined
python
# Python - 列表创建
arr1 = [1, 2, 3, 4, 5]
arr2 = [0] * 5 # [0, 0, 0, 0, 0]
arr3 = list(range(5)) # [0, 1, 2, 3, 4]
# 访问元素
print(arr1[0]) # 1
print(arr1[-1]) # 5 (负索引从末尾访问)
print(arr1[-2]) # 4
关键差异:
- Python 支持负索引,
-1表示最后一个元素 - Python 使用
*可以快速创建重复元素的列表 - Python 的
range()类似 JavaScript 的Array.from()
3.2 常用方法对比表
| 功能 | JavaScript | Python | 说明 |
|---|---|---|---|
| 添加元素(末尾) | push() |
append() |
Python 用 append |
| 添加元素(开头) | unshift() |
insert(0, item) |
Python 无 unshift |
| 删除元素(末尾) | pop() |
pop() |
相同 |
| 删除元素(开头) | shift() |
pop(0) |
Python 无 shift |
| 删除指定元素 | splice() |
remove() / del |
Python 有多种方式 |
| 查找索引 | indexOf() |
index() |
Python 找不到会报错 |
| 检查存在 | includes() |
in 关键字 |
Python 用 in |
| 切片 | slice() |
[start:end] |
Python 用切片语法 |
| 连接数组 | concat() |
+ 或 extend() |
Python 可用加号 |
| 反转 | reverse() |
reverse() |
相同 |
| 排序 | sort() |
sort() |
相同 |
| 长度 | length 属性 |
len() 函数 |
Python 用函数 |
3.3 添加和删除元素
javascript
// JavaScript - 添加元素
let arr = [1, 2, 3];
arr.push(4); // [1, 2, 3, 4] 末尾添加
arr.unshift(0); // [0, 1, 2, 3, 4] 开头添加
arr.splice(2, 0, 1.5); // [0, 1, 1.5, 2, 3, 4] 中间插入
// JavaScript - 删除元素
arr.pop(); // 删除末尾,返回 4
arr.shift(); // 删除开头,返回 0
arr.splice(1, 1); // 删除索引 1 的元素
python
# Python - 添加元素
arr = [1, 2, 3]
arr.append(4) # [1, 2, 3, 4] 末尾添加
arr.insert(0, 0) # [0, 1, 2, 3, 4] 指定位置插入
arr.insert(2, 1.5) # [0, 1, 1.5, 2, 3, 4]
# Python - 删除元素
arr.pop() # 删除末尾,返回 4
arr.pop(0) # 删除索引 0,返回 0
arr.remove(1.5) # 删除第一个值为 1.5 的元素
del arr[1] # 删除索引 1 的元素
3.4 数组遍历与转换
javascript
// JavaScript - 遍历
const numbers = [1, 2, 3, 4, 5];
// forEach
numbers.forEach(num => console.log(num));
// map
const doubled = numbers.map(num => num * 2);
// filter
const evens = numbers.filter(num => num % 2 === 0);
// reduce
const sum = numbers.reduce((acc, num) => acc + num, 0);
// find
const found = numbers.find(num => num > 3);
// some / every
const hasEven = numbers.some(num => num % 2 === 0);
const allPositive = numbers.every(num => num > 0);
python
# Python - 遍历
numbers = [1, 2, 3, 4, 5]
# for 循环
for num in numbers:
print(num)
# map (返回迭代器,需转为列表)
doubled = list(map(lambda num: num * 2, numbers))
# filter (返回迭代器)
evens = list(filter(lambda num: num % 2 == 0, numbers))
# reduce (需要导入)
from functools import reduce
sum = reduce(lambda acc, num: acc + num, numbers, 0)
# 列表推导式(更 Pythonic)
doubled = [num * 2 for num in numbers]
evens = [num for num in numbers if num % 2 == 0]
# any / all
has_even = any(num % 2 == 0 for num in numbers)
all_positive = all(num > 0 for num in numbers)
关键差异:
- Python 的
map和filter返回迭代器,需要转换为列表 - Python 推荐使用列表推导式代替
map和filter - Python 使用
any()和all()代替some()和every()
3.5 Python 独有的切片操作
python
# Python - 切片(这是 Python 的杀手级特性)
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(arr[2:5]) # [2, 3, 4] 从索引 2 到 5(不含5)
print(arr[:5]) # [0, 1, 2, 3, 4] 从开始到索引 5
print(arr[5:]) # [5, 6, 7, 8, 9] 从索引 5 到末尾
print(arr[-3:]) # [7, 8, 9] 最后 3 个元素
print(arr[::2]) # [0, 2, 4, 6, 8] 每隔一个取一个
print(arr[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 反转
# 切片赋值
arr[2:5] = [20, 30, 40]
print(arr) # [0, 1, 20, 30, 40, 5, 6, 7, 8, 9]
JavaScript 需要使用 slice() 方法,而 Python 的切片语法更简洁强大。
3.6 数组排序和反转
javascript
// JavaScript - 排序
const numbers = [3, 1, 4, 1, 5, 9];
numbers.sort((a, b) => a - b); // [1, 1, 3, 4, 5, 9]
const users = [
{name: "张三", age: 25},
{name: "李四", age: 20}
];
users.sort((a, b) => a.age - b.age);
// JavaScript - 反转
numbers.reverse();
python
# Python - 排序
numbers = [3, 1, 4, 1, 5, 9]
numbers.sort() # 原地排序,修改原列表
sorted_nums = sorted(numbers) # 返回新列表,不修改原列表
# 降序排序
numbers.sort(reverse=True)
# 复杂对象排序
users = [
{"name": "张三", "age": 25},
{"name": "李四", "age": 20}
]
users.sort(key=lambda u: u["age"])
# Python - 反转
numbers.reverse() # 原地反转
reversed_nums = numbers[::-1] # 使用切片返回新列表
四、对象与字典方法对比
4.1 创建与访问
javascript
// JavaScript - 对象创建
const user = {
name: "张三",
age: 25,
email: "zhangsan@example.com"
};
// 访问属性
console.log(user.name); // "张三" (点语法)
console.log(user["age"]); // 25 (括号语法)
console.log(user.phone); // undefined (属性不存在)
python
# Python - 字典创建
user = {
"name": "张三",
"age": 25,
"email": "zhangsan@example.com"
}
# 访问属性
print(user["name"]) # "张三" (只能用括号)
print(user.get("age")) # 25
print(user.get("phone")) # None (不存在返回 None)
print(user.get("phone", "未设置")) # "未设置" (提供默认值)
# Python 字典没有点语法访问
# print(user.name) # AttributeError
关键差异:
- JavaScript 对象的键可以不加引号,Python 字典必须加引号
- Python 字典只能用括号语法访问
- Python 推荐用
.get()方法安全访问,避免 KeyError
4.2 常用方法对比表
| 功能 | JavaScript | Python | 说明 |
|---|---|---|---|
| 获取所有键 | Object.keys() |
dict.keys() |
Python 返回视图对象 |
| 获取所有值 | Object.values() |
dict.values() |
Python 返回视图对象 |
| 获取键值对 | Object.entries() |
dict.items() |
Python 返回元组列表 |
| 检查键存在 | key in obj |
key in dict |
相同 |
| 删除属性 | delete obj.key |
del dict[key] 或 pop() |
Python 用 del |
| 合并对象 | {...obj1, ...obj2} |
{**dict1, **dict2} |
Python 用 ** |
| 浅拷贝 | {...obj} |
dict.copy() |
方式不同 |
| 清空 | obj = {} |
dict.clear() |
Python 有专门方法 |
4.3 添加、修改和删除
javascript
// JavaScript - 操作对象
let user = {name: "张三", age: 25};
// 添加属性
user.email = "zhangsan@example.com";
user["phone"] = "13800138000";
// 修改属性
user.age = 26;
// 删除属性
delete user.phone;
// 检查属性
console.log("email" in user); // true
console.log(user.hasOwnProperty("name")); // true
python
# Python - 操作字典
user = {"name": "张三", "age": 25}
# 添加键值对
user["email"] = "zhangsan@example.com"
user["phone"] = "13800138000"
# 修改值
user["age"] = 26
# 删除键值对
del user["phone"]
# 或使用 pop(返回被删除的值)
email = user.pop("email")
# 检查键是否存在
print("email" in user) # False
print("name" in user) # True
4.4 遍历对象/字典
javascript
// JavaScript - 遍历对象
const user = {name: "张三", age: 25, city: "北京"};
// for...in
for (let key in user) {
console.log(key, user[key]);
}
// Object.keys()
Object.keys(user).forEach(key => {
console.log(key, user[key]);
});
// Object.entries()
Object.entries(user).forEach(([key, value]) => {
console.log(key, value);
});
python
# Python - 遍历字典
user = {"name": "张三", "age": 25, "city": "北京"}
# 遍历键
for key in user:
print(key, user[key])
# 遍历键(显式)
for key in user.keys():
print(key)
# 遍历值
for value in user.values():
print(value)
# 遍历键值对(最常用)
for key, value in user.items():
print(key, value)
4.5 对象/字典合并
javascript
// JavaScript - 合并对象
const obj1 = {a: 1, b: 2};
const obj2 = {b: 3, c: 4};
// 使用展开运算符
const merged = {...obj1, ...obj2}; // {a: 1, b: 3, c: 4}
// Object.assign()
const merged2 = Object.assign({}, obj1, obj2);
python
# Python - 合并字典
dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}
# Python 3.9+ 使用 | 运算符
merged = dict1 | dict2 # {"a": 1, "b": 3, "c": 4}
# 使用 ** 解包
merged = {**dict1, **dict2}
# 使用 update() 方法(会修改原字典)
dict1.update(dict2)
print(dict1) # {"a": 1, "b": 3, "c": 4}
4.6 Python 独有的字典推导式
python
# 字典推导式
numbers = [1, 2, 3, 4, 5]
squared_dict = {x: x**2 for x in numbers}
print(squared_dict) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 从两个列表创建字典
keys = ["name", "age", "city"]
values = ["张三", 25, "北京"]
user = {k: v for k, v in zip(keys, values)}
# 带条件的字典推导式
even_squared = {x: x**2 for x in numbers if x % 2 == 0}
print(even_squared) # {2: 4, 4: 16}
JavaScript 需要使用 reduce() 或其他方法来实现类似功能,而 Python 的字典推导式更加简洁优雅。
五、实战案例:构建 Todo 列表管理器
让我们通过一个完整的实战项目来巩固所学知识。我们将用两种语言实现同样的 Todo 列表管理器,你可以直观地感受到它们的差异。
5.1 JavaScript 实现
javascript
class TodoList {
constructor() {
this.todos = [];
this.nextId = 1;
}
// 添加任务
addTodo(task, priority = "medium") {
const todo = {
id: this.nextId++,
task: task,
priority: priority,
completed: false,
createdAt: new Date()
};
this.todos.push(todo);
return todo;
}
// 完成任务
completeTodo(id) {
const todo = this.todos.find(t => t.id === id);
if (todo) {
todo.completed = true;
todo.completedAt = new Date();
return true;
}
return false;
}
// 删除任务
deleteTodo(id) {
const index = this.todos.findIndex(t => t.id === id);
if (index !== -1) {
this.todos.splice(index, 1);
return true;
}
return false;
}
// 获取活跃任务
getActiveTodos() {
return this.todos.filter(t => !t.completed);
}
// 获取已完成任务
getCompletedTodos() {
return this.todos.filter(t => t.completed);
}
// 按优先级获取任务
getTodosByPriority(priority) {
return this.todos.filter(t => t.priority === priority);
}
// 显示所有任务
displayTodos() {
console.log("\n=== Todo 列表 ===");
this.todos.forEach(todo => {
const status = todo.completed ? "✓" : " ";
const priority = {
high: "🔴",
medium: "🟡",
low: "🟢"
}[todo.priority];
console.log(`[${status}] ${priority} ${todo.task}`);
});
}
// 统计信息
getStats() {
const total = this.todos.length;
const completed = this.todos.filter(t => t.completed).length;
const active = total - completed;
return { total, completed, active };
}
}
// 使用示例
const myTodos = new TodoList();
myTodos.addTodo("学习 Python 基础语法", "high");
myTodos.addTodo("完成项目文档", "medium");
myTodos.addTodo("代码审查", "high");
myTodos.addTodo("团队会议", "low");
myTodos.completeTodo(1);
myTodos.displayTodos();
const stats = myTodos.getStats();
console.log(`\n总计: ${stats.total}, 已完成: ${stats.completed}, 待办: ${stats.active}`);
5.2Python 实现
python
from datetime import datetime
class TodoList:
def __init__(self):
self.todos = []
self.next_id = 1
# 添加任务
def add_todo(self, task, priority="medium"):
todo = {
"id": self.next_id,
"task": task,
"priority": priority,
"completed": False,
"created_at": datetime.now()
}
self.todos.append(todo)
self.next_id += 1
return todo
# 完成任务
def complete_todo(self, todo_id):
for todo in self.todos:
if todo["id"] == todo_id:
todo["completed"] = True
todo["completed_at"] = datetime.now()
return True
return False
# 删除任务
def delete_todo(self, todo_id):
for i, todo in enumerate(self.todos):
if todo["id"] == todo_id:
del self.todos[i]
return True
return False
# 获取活跃任务(使用列表推导式)
def get_active_todos(self):
return [t for t in self.todos if not t["completed"]]
# 获取已完成任务
def get_completed_todos(self):
return [t for t in self.todos if t["completed"]]
# 按优先级获取任务
def get_todos_by_priority(self, priority):
return [t for t in self.todos if t["priority"] == priority]
# 显示所有任务
def display_todos(self):
print("\n=== Todo 列表 ===")
priority_icons = {
"high": "🔴",
"medium": "🟡",
"low": "🟢"
}
for todo in self.todos:
status = "✓" if todo["completed"] else " "
priority = priority_icons[todo["priority"]]
print(f"[{status}] {priority} {todo['task']}")
# 统计信息
def get_stats(self):
total = len(self.todos)
completed = len([t for t in self.todos if t["completed"]])
active = total - completed
return {
"total": total,
"completed": completed,
"active": active
}
# 使用示例
my_todos = TodoList()
my_todos.add_todo("学习 Python 基础语法", "high")
my_todos.add_todo("完成项目文档", "medium")
my_todos.add_todo("代码审查", "high")
my_todos.add_todo("团队会议", "low")
my_todos.complete_todo(1)
my_todos.display_todos()
stats = my_todos.get_stats()
print(f"\n总计: {stats['total']}, 已完成: {stats['completed']}, 待办: {stats['active']}")
5.3 代码对比分析
通过这个案例,我们可以看到:
- 命名风格 :JavaScript 使用
camelCase,Python 使用snake_case - 类定义 :Python 的构造函数是
__init__,而不是constructor - 列表推导式:Python 的列表推导式让过滤操作更简洁
- 字符串格式化:Python 的 f-string 与 JavaScript 的模板字符串类似
- 方法调用 :都使用点语法,但 Python 的
self参数是显式的
六、Python 独有的强大特性
6.1 列表推导式(List Comprehension)
这是 Python 最优雅的特性之一,可以用一行代码完成复杂的列表生成和转换。
python
# 基础列表推导式
numbers = [1, 2, 3, 4, 5]
squares = [x**2 for x in numbers]
print(squares) # [1, 4, 9, 16, 25]
# 带条件的推导式
even_squares = [x**2 for x in numbers if x % 2 == 0]
print(even_squares) # [4, 16]
# 多重循环
matrix = [[i*j for j in range(1, 4)] for i in range(1, 4)]
print(matrix) # [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
# 字符串处理
words = ["hello", "world", "python"]
upper_words = [word.upper() for word in words]
print(upper_words) # ['HELLO', 'WORLD', 'PYTHON']
# 扁平化嵌套列表
nested = [[1, 2], [3, 4], [5, 6]]
flat = [item for sublist in nested for item in sublist]
print(flat) # [1, 2, 3, 4, 5, 6]
JavaScript 等价代码:
javascript
// JavaScript 需要使用 map 和 filter
const numbers = [1, 2, 3, 4, 5];
const squares = numbers.map(x => x ** 2);
const evenSquares = numbers.filter(x => x % 2 === 0).map(x => x ** 2);
// 扁平化需要使用 flat()
const nested = [[1, 2], [3, 4], [5, 6]];
const flat = nested.flat();
6.2 元组(Tuple)
元组是 Python 特有的不可变序列,类似只读数组。
python
# 创建元组
point = (10, 20)
rgb = (255, 128, 0)
# 解包
x, y = point
r, g, b = rgb
# 函数返回多个值
def get_user_info():
return "张三", 25, "北京"
name, age, city = get_user_info()
# 交换变量(Python 的优雅之处)
a, b = 1, 2
a, b = b, a # 无需临时变量!
# 元组作为字典的键(列表不可以)
locations = {
(0, 0): "原点",
(1, 0): "东",
(0, 1): "北"
}
6.3 多重赋值与解包
python
# 基础解包
first, second, third = [1, 2, 3]
# 使用 * 收集剩余元素
first, *rest, last = [1, 2, 3, 4, 5]
print(first) # 1
print(rest) # [2, 3, 4]
print(last) # 5
# 忽略某些值
name, _, age = ["张三", "male", 25]
# 嵌套解包
person = ("张三", (25, "北京"))
name, (age, city) = person
# 字典解包
user = {"name": "李四", "age": 30}
def greet(name, age):
return f"{name} is {age} years old"
print(greet(**user)) # 李四 is 30 years old
6.4 集合(Set)操作
Python 的集合操作非常强大,支持数学集合运算。
python
# 创建集合
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# 并集
print(set1 | set2) # {1, 2, 3, 4, 5, 6, 7, 8}
print(set1.union(set2)) # 同上
# 交集
print(set1 & set2) # {4, 5}
print(set1.intersection(set2))
# 差集
print(set1 - set2) # {1, 2, 3}
print(set1.difference(set2))
# 对称差集
print(set1 ^ set2) # {1, 2, 3, 6, 7, 8}
# 去重
numbers = [1, 2, 2, 3, 3, 3, 4]
unique = list(set(numbers))
print(unique) # [1, 2, 3, 4]
6.5 生成器表达式
生成器是惰性求值的,节省内存,适合处理大数据。
python
# 列表推导式(立即创建整个列表)
squares_list = [x**2 for x in range(1000000)] # 占用大量内存
# 生成器表达式(按需生成)
squares_gen = (x**2 for x in range(1000000)) # 几乎不占内存
# 使用生成器
for i, square in enumerate(squares_gen):
if i >= 5:
break
print(square) # 0, 1, 4, 9, 16
# 生成器函数
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 使用
for num in fibonacci(10):
print(num, end=" ") # 0 1 1 2 3 5 8 13 21 34
6.6 上下文管理器(with 语句)
Python 的 with 语句自动管理资源,确保正确清理。
python
# 文件操作(自动关闭文件)
with open("data.txt", "r", encoding="utf-8") as file:
content = file.read()
# 文件会自动关闭,即使发生异常
# 多个上下文
with open("input.txt") as infile, open("output.txt", "w") as outfile:
for line in infile:
outfile.write(line.upper())
七、关键差异总结
7.1 语法差异速查表
| 特性 | JavaScript | Python |
|---|---|---|
| 代码块 | 花括号 {} |
冒号 : + 缩进 |
| 语句结束 | 分号 ; (可选) |
换行 |
| 注释 | // 或 /* */ |
# 或 ''' ''' |
| 命名规范 | camelCase | snake_case |
| 常量 | const |
大写变量名(约定) |
| 自增 | i++ |
i += 1 |
| 逻辑运算 | && ` |
|
| 三元运算 | a ? b : c |
b if a else c |
| 相等判断 | === !== |
== != |
| 类型检查 | typeof |
type() |
| 打印输出 | console.log() |
print() |
7.2 真值判断差异
javascript
// JavaScript 中 falsy 值
false, 0, "", null, undefined, NaN
// 特殊情况
Boolean([]); // true (空数组是 truthy)
Boolean({}); // true (空对象是 truthy)
python
# Python 中 False 值
False, 0, "", [], {}, (), None
# 特殊情况
bool([]) # False (空列表是 False)
bool({}) # False (空字典是 False)
bool("False") # True (非空字符串都是 True)
7.3 包管理对比
| 操作 | JavaScript (npm) | Python (pip) |
|---|---|---|
| 安装包 | npm install package |
pip install package |
| 全局安装 | npm install -g package |
pip install package |
| 依赖文件 | package.json |
requirements.txt |
| 锁定版本 | package-lock.json |
Pipfile.lock |
| 列出依赖 | npm list |
pip list |
| 虚拟环境 | node_modules (项目级) |
venv / virtualenv |
八、学习建议与最佳实践
8.1 Python 编程风格(PEP 8)
Python 有官方的代码风格指南 PEP 8,遵循它可以让代码更 Pythonic:
python
# 好的风格
def calculate_average(numbers):
if not numbers:
return 0
return sum(numbers) / len(numbers)
# 不好的风格
def CalculateAverage(Numbers):
if not Numbers: return 0
return sum(Numbers)/len(Numbers)
# 导入顺序:标准库 -> 第三方库 -> 本地模块
import os
import sys
import requests
import numpy as np
from my_module import my_function
8.2 常见陷阱
1. 可变默认参数
python
# 错误:不要使用可变对象作为默认参数
def add_item(item, items=[]):
items.append(item)
return items
# 正确做法
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
2. 变量作用域
python
# Python 没有块级作用域
if True:
x = 10
print(x) # 10,x 在 if 外仍然可用
# 但有函数作用域
def func():
y = 20
# print(y) # NameError: y 未定义
8.3 从 JavaScript 到 Python 的思维转换
- 拥抱 Pythonic 风格:不要把 JavaScript 的写法直接翻译成 Python,学习使用列表推导式、生成器等 Python 特性
- 重视缩进:Python 用缩进定义代码块,这不是可选的格式化,而是语法的一部分
- 理解迭代器:Python 的很多内置函数返回迭代器而不是列表,这是为了节省内存
- 善用内置函数 :Python 有丰富的内置函数如
enumerate()、zip()、any()、all()等,学会使用它们 - 注意类型转换:Python 不会自动进行类型转换,需要显式转换
九、实用代码片段对照
9.1 异步编程
javascript
// JavaScript - Promise
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error(error);
}
}
python
# Python - asyncio
import asyncio
import aiohttp
async def fetch_data():
try:
async with aiohttp.ClientSession() as session:
async with session.get('https://api.example.com/data') as response:
data = await response.json()
return data
except Exception as error:
print(error)
# 运行异步函数
asyncio.run(fetch_data())
9.2 类与继承
python
// JavaScript - 类
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
speak() {
console.log(`${this.name} barks`);
}
}
python
# Python - 类
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} makes a sound")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
def speak(self):
print(f"{self.name} barks")
9.3 错误处理
javascript
// JavaScript
try {
const result = riskyOperation();
} catch (error) {
console.error(error.message);
} finally {
cleanup();
}
python
# Python
try:
result = risky_operation()
except ValueError as e:
print(f"值错误: {e}")
except Exception as e:
print(f"其他错误: {e}")
else:
print("成功执行") # 只在没有异常时执行
finally:
cleanup() # 总是执行
十、结语
作为前端工程师,你已经具备了扎实的编程基础,学习 Python 更多是适应新的语法和思维方式。Python 的设计哲学强调"明确胜于隐晦,简单胜于复杂",这与 JavaScript 的灵活性形成了有趣的对比。
关键要点回顾:
- 语法差异: 缩进代替花括号、snake_case 命名、显式的 self 参数
- 数据类型: 整数和浮点数分离、只有 None 没有 undefined、强大的元组
- 数组/列表: 负索引、切片语法、列表推导式
- 对象/字典: 键必须加引号、只能用括号访问、字典推导式
- 独特特性: 列表推导式、生成器、多重赋值、上下文管理器
建议学习路径:
- 先掌握基础语法,写一些小工具熟悉 Python 风格
- 学习 Python 的标准库,如
os、json、datetime等 - 根据兴趣方向深入:Web 开发(Django/Flask)、数据分析(Pandas)、自动化脚本等
- 阅读优秀的 Python 代码,学习 Pythonic 的写法
Python 和 JavaScript 各有所长,掌握两者会让你成为更全面的开发者。JavaScript 让我们理解了异步编程和前端生态,而 Python 的简洁优雅和强大的数据处理能力会打开新的视野。