第 2 章:Python 基础语法

本章将系统讲解 Python 的核心语法。每个知识点都会与 JavaScript 进行对比, 帮助你利用已有的前端知识快速建立 Python 的思维模型。掌握本章内容后,你将能独立编写大多数 Python 脚本。

2.1 变量与数据类型

Python 是动态类型语言,与 JavaScript 类似,但语法更加简洁。最大的区别是: Python 不需要 let/const/var 关键字,直接赋值即可创建变量。

变量定义

python
# Python: 直接赋值,无需声明关键字
name = "Alice"      # 字符串
age = 25            # 整数
height = 1.75       # 浮点数
is_student = True   # 布尔值

# 可以同时给多个变量赋值(解构类似 JS)
x, y, z = 1, 2, 3

# 交换变量值(无需临时变量)
a, b = 10, 20
a, b = b, a  # 现在 a=20, b=10
ℹ️与 JavaScript 的对比
特性 JavaScript Python
变量声明 let x = 1; const y = 2; x = 1; y = 2(无关键字)
常量 const PI = 3.14 PI = 3.14(约定大写,但可修改)
行尾分号 需要(可省略) 不需要
变量交换 [a, b] = [b, a] a, b = b, a

基本数据类型

python
# 使用 type() 查看类型(类似 JS 的 typeof,但更精确)
print(type(42))        # 
print(type(3.14))      # 
print(type("hello"))   # 
print(type(True))      # 
print(type(None))      #  —— 类似 JS 的 null/undefined

# 类型转换
num_str = "100"
num = int(num_str)     # 类似 parseInt()
price = float("19.99") # 类似 parseFloat()
text = str(42)         # 类似 String(42)
⚠️None 与 null/undefined 的区别

Python 中只有 None 表示"空",没有 JavaScript 中 nullundefined 的区别。 函数没有显式 return 时,默认返回 None。判断是否为 None 使用 is 关键字: if x is None:(而非 if x == None:)。

字符串操作

python
# 字符串定义:单引号、双引号、三引号都可以
name = 'Alice'
message = "Hello"
paragraph = """多行
字符串"""

# f-string 格式化(推荐,类似 JS 模板字符串)
age = 25
print(f"我叫 {name},今年 {age} 岁")

# 字符串方法(类似 JS String.prototype)
text = "  Hello World  "
print(text.strip())      # "Hello World" —— 类似 trim()
print(text.lower())      # "  hello world  " —— 类似 toLowerCase()
print(text.upper())      # "  HELLO WORLD  " —— 类似 toUpperCase()
print(text.replace("World", "Python"))  # "  Hello Python  "

# 分割与连接
words = "a,b,c".split(",")  # ['a', 'b', 'c'] —— 类似 split()
result = "-".join(words)     # "a-b-c" —— JS 中需用 Array.prototype.join()

f-string 高级格式化

Python 的 f-string 远不止简单的变量插入。以下是一些前端开发中常用的高级技巧:

python
# 数字千分位(类似 JS 的 toLocaleString())
amount = 1234567.89
print(f"金额: {amount:,.2f}")  # 金额: 1,234,567.89
# JS: amount.toLocaleString('en-US', { minimumFractionDigits: 2 })

# 百分比
ratio = 0.856
print(f"完成率: {ratio:.1%}")   # 完成率: 85.6%

# 对齐与填充
name = "Python"
print(f"|{name:>15}|")   # |         Python| 右对齐
print(f"|{name:<15}|")   # |Python         | 左对齐
print(f"|{name:^15}|")   # |    Python     | 居中
print(f"|{name:*^15}|")  # |****Python*****| 用 * 填充

# 日期格式化
from datetime import datetime
now = datetime.now()
print(f"当前时间: {now:%Y-%m-%d %H:%M:%S}")
# 相当于 JS 的 dayjs().format('YYYY-MM-DD HH:mm:ss')

# 调用表达式(类似 JS 的 ${fn()})
def greet(name):
    return f"Hello, {name}"

print(f"{greet('World')}")  # Hello, World

# = 说明符(Python 3.8+):同时显示变量名和值(调试利器!)
x = 10
y = 20
print(f"{x + y = }")  # x + y = 30
# 相当于 console.log({x}, {y}, x + y)

2.2 数据结构

Python 内置了四种核心数据结构,分别对应 JavaScript 中的不同概念。掌握它们是编写 Python 代码的基础。

列表 list —— 类似 JavaScript 的 Array

python
# 创建列表(类似 JS 数组)
fruits = ["apple", "banana", "cherry"]
mixed = [1, "two", 3.0, True]  # 可以混合类型(但不推荐)

# 索引访问(与 JS 相同,从 0 开始)
print(fruits[0])   # "apple"
print(fruits[-1])  # "cherry" —— 负数索引从末尾开始,JS 中需用 at(-1)

# 切片操作(Python 特有,非常强大)
print(fruits[0:2])   # ["apple", "banana"] —— 索引 0 到 1(不含 2)
print(fruits[:2])    # ["apple", "banana"] —— 从头开始
print(fruits[1:])    # ["banana", "cherry"] —— 到末尾
print(fruits[::2])   # ["apple", "cherry"] —— 步长为 2
print(fruits[::-1])  # ["cherry", "banana", "apple"] —— 反转!

# 常用方法
fruits.append("orange")      # 末尾添加,类似 push()
fruits.insert(1, "mango")    # 指定位置插入,类似 splice()
fruits.remove("banana")      # 删除第一个匹配项(JS 需用 filter 或 splice)
popped = fruits.pop()        # 删除并返回末尾元素,类似 pop()
print(len(fruits))           # 获取长度,类似 .length
💡切片语法速记

Python 的 [start:end:step] 切片是处理序列的利器。记住: start 包含,end 不包含。省略即表示"从头"或"到尾"。

字典 dict —— 类似 JavaScript 的 Object / Map

python
# 创建字典(类似 JS 对象字面量)
user = {
    "name": "Alice",
    "age": 25,
    "is_admin": False
}

# 访问值
print(user["name"])        # "Alice"
print(user.get("email"))   # None —— 安全访问,不会报错
print(user.get("email", "default@example.com"))  # 提供默认值

# 添加 / 修改
user["email"] = "alice@example.com"
user["age"] = 26

# 删除
del user["is_admin"]       # 类似 delete user.isAdmin

# 遍历(类似 Object.entries())
for key, value in user.items():
    print(f"{key}: {value}")

# 仅遍历键或值
for key in user.keys():      # 类似 Object.keys()
    print(key)
for value in user.values():  # 类似 Object.values()
    print(value)
ℹ️dict 与 JS Object 的关键差异
  • 字典的键可以是任意不可变类型(数字、字符串、元组),不限于字符串
  • 字典没有属性访问语法(user.name 会报错),必须用 user["name"]
  • 字典保持插入顺序(Python 3.7+),与 JS 对象相同
  • 字典是独立的类型,不是 Object 的原型链体系

元组 tuple —— 不可变的列表

python
# 元组使用圆括号定义,创建后不可修改
point = (10, 20)
coordinates = (1, 2, 3)

# 单元素元组需要逗号!
single = (42,)  # 注意逗号
not_tuple = (42)  # 这只是整数 42

# 元组解包( unpacking,类似 JS 解构)
x, y = point
print(x, y)  # 10 20

# 函数返回多个值时,实际返回的是元组
def get_min_max(numbers):
    return min(numbers), max(numbers)

minimum, maximum = get_min_max([3, 1, 4, 1, 5])
print(minimum, maximum)  # 1 5
💡何时使用元组?

当你有一组不应被修改的数据时,使用元组。元组比列表更轻量,且可作为字典的键(因为不可变)。 常见场景:坐标点、RGB 颜色值、数据库记录等。

集合 set —— 类似数学集合,去重利器

python
# 创建集合(自动去重,无序)
numbers = {1, 2, 3, 3, 3}
print(numbers)  # {1, 2, 3}

# 从列表创建集合(快速去重)
items = ["a", "b", "a", "c", "b"]
unique = set(items)
print(unique)  # {'a', 'b', 'c'}

# 集合运算(数学集合操作)
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

print(a | b)   # {1, 2, 3, 4, 5, 6} —— 并集(类似 JS Set union)
print(a & b)   # {3, 4} —— 交集
print(a - b)   # {1, 2} —— 差集
print(a ^ b)   # {1, 2, 5, 6} —— 对称差集

列表推导式 —— Python 的"语法糖"

列表推导式是 Python 最具特色的语法之一,用一行代码替代循环和 filter/map:

python
# 传统方式(类似 JS 的 for...of + push)
squares = []
for x in range(10):
    squares.append(x ** 2)

# 列表推导式(一行搞定)
squares = [x ** 2 for x in range(10)]

# 带条件的列表推导式(类似 filter + map)
evens = [x for x in range(20) if x % 2 == 0]

# JS 对比:
// const evens = Array.from({length: 20}, (_, i) => i).filter(x => x % 2 === 0);

# 字典推导式
word_lengths = {word: len(word) for word in ["apple", "banana", "cherry"]}
# {'apple': 5, 'banana': 6, 'cherry': 6}

# 集合推导式
square_set = {x ** 2 for x in range(100)}  # 自动去重

collections 模块 —— 高效数据结构

Python 的 collections 模块提供了 list/dict/tuple/set 之外的高级数据结构。 以下三种是最常用的,它们在性能和可读性上都优于手动实现的等价方案:

python
from collections import defaultdict, Counter, deque

# 1. defaultdict —— 带默认值的字典
# 不需要先检查 key 是否存在再初始化,类似 JS Map 的 getOrDefault
word_count = defaultdict(int)
sentence = "hello world hello python".split()
for word in sentence:
    word_count[word] += 1  # 不存在时自动初始化为 0
print(dict(word_count))  # {'hello': 2, 'world': 1, 'python': 1}

# 按分类收集数据
users_by_role = defaultdict(list)
users = [("Alice", "admin"), ("Bob", "user"), ("Charlie", "admin")]
for name, role in users:
    users_by_role[role].append(name)
print(dict(users_by_role))
# {'admin': ['Alice', 'Charlie'], 'user': ['Bob']}

# 2. Counter —— 计数器(统计频率的利器)
colors = ["red", "blue", "red", "green", "blue", "red"]
cnt = Counter(colors)
print(cnt)              # Counter({'red': 3, 'blue': 2, 'green': 1})
print(cnt.most_common(2))  # [('red', 3), ('blue', 2)] —— 前 N 名

# 支持数学运算
cnt2 = Counter(["red", "green"])
print(cnt + cnt2)       # Counter({'red': 4, 'blue': 2, 'green': 2})
print(cnt - cnt2)       # Counter({'red': 2, 'blue': 2})

# 3. deque —— 双端队列(高性能的头部操作)
# list 在头部插入/删除是 O(n),deque 是 O(1)
history = deque(maxlen=5)  # 最多保留 5 条记录
for i in range(10):
    history.append(i)
print(history)  # deque([5, 6, 7, 8, 9], maxlen=5)

# 灵活的双端操作
d = deque(["a", "b", "c"])
d.appendleft("x")        # 左侧追加
d.append("y")            # 右侧追加
print(d)  # deque(['x', 'a', 'b', 'c', 'y'])
💡使用建议
  • defaultdict:取代 if key not in dict: dict[key] = [] 的重复代码
  • Counter:统计词频、投票计数、排名榜等场景
  • deque:队列、栈、滑动窗口、历史记录等场景

2.3 控制流

Python 的控制流结构与 JavaScript 类似,但语法更简洁。核心区别在于: 用缩进表示代码块,而非大括号。

条件语句 if/elif/else

python
score = 85

if score >= 90:
    grade = "A"
elif score >= 80:      # elif = else if,注意不是 "else if"
    grade = "B"
elif score >= 70:
    grade = "C"
else:
    grade = "D"

print(f"成绩等级: {grade}")

# 三元表达式(类似 JS 的条件运算符)
status = "及格" if score >= 60 else "不及格"
# JS: const status = score >= 60 ? "及格" : "不及格";
⚠️缩进是语法的一部分!

Python 使用 4 个空格作为标准缩进(不要用 Tab)。缩进错误会导致 IndentationError。 建议配置编辑器将 Tab 自动转换为 4 个空格。

for 循环 —— 遍历而非索引

python
# Python 的 for 循环直接遍历元素(类似 JS 的 for...of)
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

# 如果需要索引,使用 enumerate()(类似 JS 的 entries())
for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")
# 0: apple
# 1: banana
# 2: cherry

# 遍历字典
user = {"name": "Alice", "age": 25}
for key, value in user.items():
    print(f"{key} = {value}")

# range() 生成数字序列(类似 JS 的 for (let i = 0; i < n; i++))
for i in range(5):       # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 10, 2):  # 2, 4, 6, 8(起始, 结束, 步长)
    print(i)

while 循环与 break/continue

python
# while 循环(与 JS 语法相同)
count = 0
while count < 5:
    print(count)
    count += 1  # Python 没有 count++ 语法!

# break 和 continue(与 JS 完全相同)
for num in range(10):
    if num == 3:
        continue    # 跳过当前迭代
    if num == 7:
        break       # 终止循环
    print(num)
# 输出: 0, 1, 2, 4, 5, 6

# else 子句(Python 特有!循环正常结束时执行)
for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            break
    else:  # 注意缩进!没有触发 break 时执行
        print(f"{n} 是质数")
# 输出: 2, 3, 5, 7 是质数
ℹ️for...else 的用途

for...else 是 Python 的独特语法。当循环没有被 break 中断时,else 块会执行。 这在搜索场景中非常有用——如果找到目标就 break,否则执行 else 中的"未找到"逻辑。

2.4 函数

Python 使用 def 关键字定义函数。与 JavaScript 相比,Python 的函数参数系统更加灵活和强大。

基础函数定义

python
# 基础函数(类似 JS 的 function 声明)
def greet(name):
    """函数的文档字符串(docstring),说明函数用途"""
    return f"Hello, {name}!"

print(greet("Alice"))  # Hello, Alice!

# 多返回值(实际是返回元组)
def get_stats(numbers):
    return min(numbers), max(numbers), sum(numbers) / len(numbers)

min_val, max_val, avg = get_stats([1, 2, 3, 4, 5])
print(min_val, max_val, avg)  # 1 5 3.0

参数类型详解

python
# 1. 位置参数(默认方式)
def power(base, exponent):
    return base ** exponent

print(power(2, 3))  # 8

# 2. 默认参数(类似 JS 的默认参数)
def greet(name, greeting="Hello"):
    return f"{greeting}, {name}!"

print(greet("Alice"))           # Hello, Alice!
print(greet("Bob", "Hi"))       # Hi, Bob!

# ⚠️ 默认参数不要使用可变对象!
def bad_append(item, items=[]):  # 错误!
    items.append(item)
    return items

def good_append(item, items=None):  # 正确做法
    if items is None:
        items = []
    items.append(item)
    return items

# 3. *args —— 接收任意数量的位置参数(类似 JS 的 ...args)
def sum_all(*args):
    return sum(args)

print(sum_all(1, 2, 3, 4))  # 10
# args 是一个元组: (1, 2, 3, 4)

# 4. **kwargs —— 接收任意数量的关键字参数(类似 JS 的对象解构剩余属性)
def create_user(**kwargs):
    return {
        "name": kwargs.get("name", "Anonymous"),
        "age": kwargs.get("age", 0),
        **kwargs  # 展开其他属性
    }

user = create_user(name="Alice", age=25, email="alice@example.com")

# 5. 组合使用(顺序: 位置参数, 默认参数, *args, **kwargs)
def func(a, b=2, *args, **kwargs):
    print(f"a={a}, b={b}, args={args}, kwargs={kwargs}")

func(1, 3, 4, 5, x=10, y=20)
# a=1, b=3, args=(4, 5), kwargs={'x': 10, 'y': 20}

lambda 表达式

python
# lambda 语法(只能写单行表达式)
square = lambda x: x ** 2
print(square(5))  # 25

# 常用于排序和过滤(类似 JS 的箭头函数)
users = [
    {"name": "Alice", "age": 30},
    {"name": "Bob", "age": 25},
    {"name": "Charlie", "age": 35}
]

# 按年龄排序
users_sorted = sorted(users, key=lambda u: u["age"])

# JS 对比:
// const usersSorted = users.sort((a, b) => a.age - b.age);
ℹ️lambda 的限制

Python 的 lambda 比 JS 箭头函数受限更多:只能包含单个表达式,不能写语句(如赋值、循环)。 复杂逻辑应使用普通 def 函数。如果你需要类似 JS 箭头函数的灵活性,直接写命名函数即可。

生成器(Generator)—— 惰性计算的利器

生成器是 Python 最具特色的功能之一,它允许你按需生成数据,而不是一次性把所有数据加载到内存中。 如果把列表比作"一次性把所有菜端上桌",生成器就是"你点一道做一道"。

python
# === 生成器函数:使用 yield 逐值返回 ===
def fibonacci(n):
    """生成前 n 个斐波那契数(惰性生成,不占内存)"""
    a, b = 0, 1
    for _ in range(n):
        yield a  # yield 类似 return,但函数不会退出
        a, b = b, a + b

# 使用生成器
for num in fibonacci(10):
    print(num, end=" ")  # 0 1 1 2 3 5 8 13 21 34

# 转为列表(惰性 -> 立即求值)
fib_list = list(fibonacci(10))
print(fib_list)  # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

# === 生成器表达式(类似列表推导式,但用小括号)===
# 列表推导式:一次性创建所有元素(占内存)
squares_list = [x**2 for x in range(10**6)]  # 100万个元素的列表

# 生成器表达式:按需生成(几乎不占内存)
squares_gen = (x**2 for x in range(10**6))   # 生成器对象

print(squares_gen)  # 
print(next(squares_gen))  # 0(取第一个值)
print(next(squares_gen))  # 1(取第二个值)

# === 实战:逐行读取大文件(不会撑爆内存)===
def read_large_file(filepath):
    """逐行读取文件,适合 GB 级别的大文件"""
    with open(filepath, "r", encoding="utf-8") as f:
        for line in f:
            yield line.strip()

# 处理大文件
for line in read_large_file("big_data.log"):
    if "ERROR" in line:
        print(line)
ℹ️生成器 vs 列表
特性 列表 生成器
内存占用 存储全部元素 只存储当前元素
遍历次数 可多次遍历 只能遍历一次
索引访问 支持 list[5] 不支持
创建速度 慢(需要计算所有值) 快(立即返回)
适用场景 小数据、需要多次访问 大数据、流式处理、管道
JS 类比 Array AsyncIterator / Generator

2.5 面向对象

Python 的面向对象编程与 JavaScript 的 class 语法有许多相似之处,但也有独特的设计哲学。

类与实例

python
class User:
    # 类属性(类似 JS 的静态属性,所有实例共享)
    species = "Homo sapiens"

    # __init__ 是构造方法(类似 JS 的 constructor)
    def __init__(self, name, age):
        # self 相当于 JS 的 this,但必须显式作为第一个参数
        self.name = name      # 实例属性
        self._age = age       # 单下划线表示"私有"(约定,非强制)

    # 实例方法
    def greet(self):
        return f"Hello, I'm {self.name}"

    # 类方法(类似 JS 的 static 方法,但接收 cls)
    @classmethod
    def create_anonymous(cls):
        return cls("Anonymous", 0)

    # 静态方法(类似 JS 的 static 方法,不接收 self/cls)
    @staticmethod
    def is_adult(age):
        return age >= 18

# 创建实例(不需要 new 关键字!)
alice = User("Alice", 25)
print(alice.greet())  # Hello, I'm Alice

# 访问类属性
print(User.species)   # Homo sapiens
ℹ️self 与 this 的对比
特性 JavaScript Python
实例引用 this(隐式) self(必须显式声明)
创建实例 new User() User()(无 new)
构造函数 constructor() __init__(self)
方法定义 greet() {} def greet(self):

继承

python
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        raise NotImplementedError("子类必须实现此方法")

class Dog(Animal):  # 继承语法: class 子类(父类)
    def __init__(self, name, breed):
        super().__init__(name)  # 调用父类构造(类似 super())
        self.breed = breed

    def speak(self):
        return f"{self.name} says: Woof!"

class Cat(Animal):
    def speak(self):
        return f"{self.name} says: Meow!"

dog = Dog("Buddy", "Golden Retriever")
cat = Cat("Whiskers")

print(dog.speak())  # Buddy says: Woof!
print(cat.speak())  # Whiskers says: Meow!

魔术方法(Dunder Methods)

魔术方法以双下划线开头和结尾,让你自定义类的行为,类似 JS 的 Symbol 方法:

python
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    # 字符串表示(类似 JS 的 toString())
    def __str__(self):
        return f"Vector({self.x}, {self.y})"

    # 开发者友好的表示(类似 JS 的 inspect 或 toJSON)
    def __repr__(self):
        return f"Vector(x={self.x}, y={self.y})"

    # 加法运算符重载(JS 中需用 Symbol.toPrimitive 或 valueOf)
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    # 相等比较(类似 JS 的 == 或 Object.is)
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    # 长度(类似 JS 的 valueOf 或自定义属性)
    def __len__(self):
        return int((self.x ** 2 + self.y ** 2) ** 0.5)

v1 = Vector(2, 3)
v2 = Vector(4, 5)

print(str(v1))       # Vector(2, 3)
print(repr(v1))      # Vector(x=2, y=3)
print(v1 + v2)       # Vector(6, 8)
print(v1 == Vector(2, 3))  # True
print(len(v1))       # 3
💡常用魔术方法速查
Python 作用 JS 类比
__init__ 构造函数 constructor()
__str__ 用户友好的字符串 toString()
__repr__ 开发者调试字符串 inspect / 调试器显示
__eq__ == 比较 [Symbol.toPrimitive]
__len__ len() 函数 .length getter
__getitem__ 索引访问 [] Proxy get trap

2.6 异常处理

Python 的异常处理结构与 JavaScript 的 try/catch 非常相似,但功能更完善,支持 else 和 finally 子句。

python
# 基础异常处理
def divide(a, b):
    try:
        result = a / b
    except ZeroDivisionError:
        print("错误:不能除以零!")
        return None
    except TypeError as e:
        print(f"类型错误: {e}")
        return None
    else:
        # try 成功执行且没有异常时运行
        print("计算成功!")
        return result
    finally:
        # 无论是否异常都会执行(常用于清理资源)
        print("计算结束")

print(divide(10, 2))   # 计算成功! 计算结束 5.0
print(divide(10, 0))   # 错误:不能除以零! 计算结束 None

常见异常类型

异常类型 触发场景 JS 类比
ValueError 值类型正确但内容不合法 RangeError / 类型转换错误
TypeError 操作或函数应用于不适当类型 TypeError
KeyError 字典中访问不存在的键 访问对象不存在的属性
IndexError 序列索引超出范围 RangeError(数组越界)
FileNotFoundError 文件不存在 Node.js fs 模块错误
ImportError 导入模块失败 MODULE_NOT_FOUND

自定义异常

python
# 继承 Exception 创建自定义异常(类似 JS 的 class extends Error)
class ValidationError(Exception):
    """数据验证失败时抛出"""
    def __init__(self, field, message):
        self.field = field
        self.message = message
        super().__init__(f"[{field}] {message}")

class User:
    def __init__(self, name, age):
        if not name or len(name) < 2:
            raise ValidationError("name", "姓名至少需要 2 个字符")
        if age < 0 or age > 150:
            raise ValidationError("age", "年龄必须在 0-150 之间")
        self.name = name
        self.age = age

try:
    user = User("A", 200)
except ValidationError as e:
    print(f"验证失败: {e}")
    # 输出: 验证失败: [name] 姓名至少需要 2 个字符

2.7 文件操作

Python 的文件操作比 Node.js 更直观,内置的 open() 函数和 with 语句让资源管理变得简单安全。

基础读写

python
# 写入文件(类似 fs.writeFileSync)
with open("hello.txt", "w", encoding="utf-8") as f:
    f.write("Hello, Python!\n")
    f.write("第二行内容\n")
# with 语句自动关闭文件,无需手动 f.close()

# 读取文件(类似 fs.readFileSync)
with open("hello.txt", "r", encoding="utf-8") as f:
    content = f.read()       # 读取全部内容
    print(content)

# 逐行读取(类似 readline 接口)
with open("hello.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())  # strip() 去除换行符

# 读取为列表
with open("hello.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()    # ['Hello, Python!\n', '第二行内容\n']
⚠️务必指定 encoding="utf-8"

Windows 系统默认编码可能是 GBK,不指定 encoding 会导致中文乱码。 始终显式指定 encoding="utf-8",这是最佳实践。

with 语句与上下文管理器

python
# with 语句确保资源正确释放(类似 JS 的 try...finally)
# 即使发生异常,文件也会被关闭

# 传统写法(不推荐)
f = open("file.txt", "r")
try:
    data = f.read()
finally:
    f.close()  # 必须手动关闭

# with 写法(推荐)
with open("file.txt", "r") as f:
    data = f.read()
# 自动关闭,即使出错

# 自定义上下文管理器
from contextlib import contextmanager

@contextmanager
def managed_resource(name):
    print(f"获取资源: {name}")
    yield name  # yield 之前的代码是 __enter__,之后是 __exit__
    print(f"释放资源: {name}")

with managed_resource("数据库连接") as res:
    print(f"使用资源: {res}")
# 输出:
# 获取资源: 数据库连接
# 使用资源: 数据库连接
# 释放资源: 数据库连接

pathlib —— 现代路径处理

pathlib 是 Python 3.4+ 引入的现代路径库,比传统的 os.path 更直观:

python
from pathlib import Path

# 创建路径对象(自动处理 Windows/Unix 路径差异)
project_dir = Path("/home/user/project")
data_file = project_dir / "data" / "users.json"  # 使用 / 拼接路径!

print(data_file)           # /home/user/project/data/users.json
print(data_file.name)      # users.json(文件名)
print(data_file.stem)      # users(不含扩展名)
print(data_file.suffix)    # .json(扩展名)
print(data_file.parent)    # /home/user/project/data(父目录)

# 路径检查
print(data_file.exists())       # False(检查是否存在)
print(data_file.is_file())      # False
print(data_file.is_dir())       # False

# 创建目录(类似 mkdir -p)
output_dir = Path("output")
output_dir.mkdir(parents=True, exist_ok=True)

# 遍历目录(类似 fs.readdir)
for file in Path(".").glob("*.py"):  # 匹配当前目录的 .py 文件
    print(file)

# 递归遍历
for file in Path(".").rglob("*.txt"):  # 递归查找所有 .txt
    print(file)
💡pathlib 与 os.path 的选择

新项目优先使用 pathlib,API 更现代、面向对象、跨平台。 维护旧代码时可能会遇到 os.path,两者可以互相转换: Path("file.txt").__str__() 得到字符串路径。

2.8 模块与包

Python 的模块系统与 JavaScript 的 ES Modules / CommonJS 类似,用于组织代码和复用功能。

导入模块

python
# 1. 导入整个模块(类似 import * as os from 'os')
import os
print(os.getcwd())  # 获取当前工作目录

# 2. 从模块导入特定内容(类似 import { pi, sin } from 'math')
from math import pi, sqrt
print(pi)
print(sqrt(16))  # 4.0

# 3. 导入并重命名(类似 import * as m from 'math')
import datetime as dt
now = dt.datetime.now()

# 4. 导入所有(不推荐,会污染命名空间)
from math import *
print(sin(pi / 2))  # 1.0

# 5. 相对导入(包内部使用)
# from . import module      # 同级目录
# from .. import parent     # 上级目录
# from .utils import helper # 子模块

__name__ == '__main__'

这是 Python 中最常见的惯用法,用于判断模块是被直接运行还是被导入:

python
# utils.py
def helper():
    return "I'm a helper"

# 当直接运行 python utils.py 时,__name__ 是 '__main__'
# 当从其他文件 import utils 时,__name__ 是 'utils'
if __name__ == "__main__":
    # 这部分代码只在直接运行时执行
    print("测试 helper 函数:")
    print(helper())

# JS 类比:
// if (require.main === module) { ... }
// 或 ES Module 的 import.meta.main
ℹ️为什么需要 __name__ == '__main__'?

想象你写了一个工具模块,里面有一些测试代码。当你直接运行文件时,希望测试代码执行; 但当其他文件导入你的模块时,不希望测试代码干扰。这个惯用法完美解决了这个问题。

标准库简介

Python 以"内置电池"著称,标准库功能丰富。以下是前端开发者最常用的一些模块:

模块 用途 前端 / Node.js 类比
os 操作系统接口 os / process
sys 系统相关参数和函数 process.argv, process.exit()
pathlib 面向对象的路径操作 path 模块
json JSON 编码解码 JSON.parse/stringify
re 正则表达式 RegExp
datetime 日期和时间处理 Date / dayjs
collections 高级数据结构
itertools 迭代器工具
functools 高阶函数工具
urllib URL 处理 URL / URLSearchParams
python
# 常用标准库示例
import json
from datetime import datetime, timedelta

# JSON 处理(与 JS 几乎相同)
data = {"name": "Alice", "age": 25}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
parsed = json.loads(json_str)

# 日期时间(类似 dayjs/moment)
now = datetime.now()
future = now + timedelta(days=7)
print(future.strftime("%Y-%m-%d"))  # 格式化输出
ℹ️本章小结

本章涵盖了 Python 的核心语法:变量与数据类型、四种核心数据结构(list/dict/tuple/set)、 控制流、函数定义(含 *args/**kwargs)、面向对象编程、异常处理、文件操作以及模块系统。

作为前端开发者,你会发现 Python 的语法更加简洁一致,而 JavaScript 的灵活性更高。 掌握这些基础后,你已经可以编写绝大多数 Python 脚本。下一章将介绍 Python 工程化实践, 包括项目结构、虚拟环境、测试和类型提示等内容。