AI全栈实战 | 3.2-01 Python 基础:四大数据容器怎么选,推导式为什么是 Pythonic 的灵魂

上篇回顾 :3.1-01 讲了 Python 虚拟环境的必要性(与 Java Maven 依赖机制对比)+ uv/pyproject.toml 现代工具链。本篇进入 Python 基础语法------对学完 Java 的你来说,Python 语法本身不难,难的是写出 Pythonic 的代码而不是「用 Python 写 Java」。

一、开篇:用 Python 写 Java 的典型症状

学完 Java 转 Python,最容易写出这种代码:

python 复制代码
# Java 风格的 Python(能跑但不 Pythonic)
words = ["hello", "world", "python"]
result = []
for i in range(len(words)):
    result.append(words[i].upper())
print(result)

Pythonic 的写法:

python 复制代码
words = ["hello", "world", "python"]
result = [w.upper() for w in words]
print(result)

同样是遍历转大写,Pythonic 版本用推导式一行搞定。本篇把 Python 四大容器、推导式、函数一等公民、异常哲学、鸭子类型讲透,帮你从「用 Python 写 Java」升级到「写 Pythonic 代码」。

二、四大数据容器

2.1 对照表

Python Java 对应 可变 有序 重复
list ArrayList ✅ ✅ ✅
dict HashMap ✅ ✅(3.7+) 键不重复
tuple (无直接对应) ❌ ✅ ✅
set HashSet ✅ ❌ ❌

2.2 list 列表

python 复制代码
# 创建
nums = [1, 2, 3, 4, 5]

# 索引(支持负数)
nums[0]    # 1
nums[-1]   # 5(最后一个)

# 切片
nums[1:3]  # [2, 3]
nums[:3]   # [1, 2, 3]
nums[::2]  # [1, 3, 5](步长 2)

# 增删
nums.append(6)
nums.insert(0, 0)
nums.pop()      # 删除并返回最后一个
nums.remove(3)  # 删除第一个值为 3 的元素

2.3 dict 字典

python 复制代码
# 创建
user = {"name": "Tom", "age": 18}

# 访问
user["name"]            # "Tom"
user.get("email", "")   # 不存在返回默认值

# 增改
user["email"] = "tom@example.com"
user.update({"age": 20, "phone": "123"})

# 遍历
for key, value in user.items():
    print(key, value)

2.4 tuple 元组

python 复制代码
# 创建
point = (3, 4)
single = (1,)    # 单元素要加逗号

# 不可变
point[0] = 5    # TypeError!

# 用途
def get_user():
    return "Tom", 18    # 返回元组(省略括号)

name, age = get_user()  # 解构

2.5 set 集合

python 复制代码
# 创建
nums = {1, 2, 3, 2}   # {1, 2, 3}(自动去重)

# 运算
a = {1, 2, 3}
b = {2, 3, 4}
a & b   # {2, 3} 交集
a | b   # {1, 2, 3, 4} 并集
a - b   # {1} 差集

2.6 容器选型决策

需求 选
有序、可变、可重复 list
键值对 dict
不可变、有序 tuple
去重 set
有序去重 dict(Python 3.7+ 保序)

三、切片:Python 的优雅利器

python 复制代码
s = "Hello, World"

s[0:5]    # "Hello"
s[7:]     # "World"
s[-5:]    # "World"
s[::-1]   # "dlroW ,olleH"(反转)
s[::2]    # "HloWrd"(每隔一个字符)

切片对 list/tuple/str/bytes 都适用。Java 没有等价语法(要写循环或 substring 拼接)。

四、推导式:Pythonic 的灵魂

4.1 列表推导式

python 复制代码
# 传统
squares = []
for i in range(10):
    squares.append(i ** 2)

# 推导式
squares = [i ** 2 for i in range(10)]

# 带条件
evens = [i for i in range(10) if i % 2 == 0]

# 嵌套
matrix = [[i * j for j in range(3)] for i in range(3)]

4.2 字典/集合推导式

python 复制代码
# 字典
word_len = {w: len(w) for w in ["hello", "world", "py"]}

# 集合
unique_lens = {len(w) for w in words}

4.3 生成器表达式(惰性)

python 复制代码
# 列表推导式:立即生成(占内存)
squares = [i ** 2 for i in range(1000000)]   # ~8MB

# 生成器表达式:惰性生成(不占内存)
squares_gen = (i ** 2 for i in range(1000000))   # ~100B
sum(squares_gen)   # 按需计算

大数据集用生成器表达式,避免内存爆炸。

五、函数一等公民

5.1 函数可以赋值、传递、返回

python 复制代码
def greet(name):
    return f"Hello, {name}"

# 赋值
say_hello = greet
say_hello("Tom")   # "Hello, Tom"

# 传递
def apply(func, value):
    return func(value)
apply(greet, "Tom")

# 返回(高阶函数)
def make_multiplier(n):
    def multiply(x):
        return x * n
    return multiply

double = make_multiplier(2)
double(5)   # 10

5.2 lambda 匿名函数

python 复制代码
# 排序
users = [{"name": "Tom", "age": 20}, {"name": "Jerry", "age": 18}]
sorted(users, key=lambda u: u["age"])   # 按 age 排序

# map/filter
nums = [1, 2, 3, 4, 5]
list(map(lambda x: x ** 2, nums))       # [1, 4, 9, 16, 25]
list(filter(lambda x: x % 2 == 0, nums))  # [2, 4]

但 Pythonic 更推荐用推导式替代 map/filter:

python 复制代码
[x ** 2 for x in nums]       # 替代 map
[x for x in nums if x % 2 == 0]  # 替代 filter

六、作用域 LEGB

Python 查找变量的顺序:L → E → G → B

层 说明
L (Local) 函数内局部
E (Enclosing) 外层嵌套函数
G (Global) 模块全局
B (Built-in) 内置(len/range/print)
python 复制代码
x = "global"

def outer():
    x = "enclosing"
    def inner():
        x = "local"
        print(x)   # local
    inner()
    print(x)       # enclosing

七、异常处理哲学:EAFP vs LBYL

7.1 两种风格

风格 全称 含义
EAFP Easier to Ask Forgiveness than Permission 先做,出错再处理
LBYL Look Before You Leap 先检查,再做

7.2 Java 是 LBYL

java 复制代码
if (map.containsKey(key)) {
    return map.get(key);
}

7.3 Python 推荐 EAFP

python 复制代码
try:
    return map[key]
except KeyError:
    return None

为什么 Python 推荐 EAFP:

  1. 避免 TOCTOU(检查与使用之间的竞态)
  2. 性能更好(异常只在出错时才有开销,检查每次都要执行)
  3. 更 Pythonic

八、鸭子类型

8.1 什么是鸭子类型

如果它走起来像鸭子、叫起来像鸭子,那它就是鸭子。

Python 不关心对象的类型,只关心它有没有需要的方法/属性。

python 复制代码
def make_sound(animal):
    animal.speak()   # 不检查类型,只要有 speak 方法

class Dog:
    def speak(self): print("Woof")

class Cat:
    def speak(self): print("Meow")

make_sound(Dog())   # Woof
make_sound(Cat())   # Meow

8.2 与 Java 接口的对比

Java 要定义接口、显式 implements:

java 复制代码
interface Animal { void speak(); }
class Dog implements Animal { public void speak() { ... } }

Python 不需要接口------有方法就行。更灵活但少了编译时检查。

8.3 type hints 弥补类型安全

python 复制代码
from typing import Protocol

class Animal(Protocol):
    def speak(self) -> str: ...

def make_sound(animal: Animal) -> None:
    animal.speak()

class Dog:
    def speak(self) -> str: return "Woof"

make_sound(Dog())   # mypy 检查通过
make_sound("string")  # mypy 报错(没有 speak 方法)

Protocol 是 Python 3.8+ 的结构化类型------不要求显式继承,只要有对应方法就算符合。配合 mypy 做静态检查。

九、动态类型的灵活性什么时候变成灾难

9.1 灵活的场景

  • 快速原型开发
  • 数据处理脚本(pandas/numpy)
  • 自动化运维
  • Web 后端(FastAPI/Flask)

9.2 灾难的场景

  • 大型团队协作(类型不明确导致误解)
  • 长期维护的项目(重构时没有类型保护)
  • 复杂业务逻辑(类型错误运行时才暴露)

9.3 type hints + mypy 能救回静态世界吗

部分能------type hints 是可选的,mypy 是额外工具。不会像 Java 那样强制。但加上 type hints 后:

  1. IDE 补全更智能
  2. 重构更安全
  3. 团队协作更清晰

推荐:项目用 type hints,但不过度追求 100% 类型覆盖。核心接口和数据模型必须标注,脚本和小工具可以省略。

十、小结表

概念 Python Java 对照
四大容器 list/dict/tuple/set ArrayList/HashMap/HashSet
切片 s1:3 substring/Arrays.copyOfRange
推导式 x for x in nums Stream API
函数一等公民 可赋值传递返回 Lambda/函数式接口
异常哲学 EAFP LBYL
鸭子类型 有方法就行 显式 implements
相关推荐
Mr_Macallon1 小时前
C++回顾(基础)(01)
c语言·开发语言·c++·学习
计算机毕业编程指导师1 小时前
【大数据毕设选题推荐】基于Spark的WTA职业网球赛事演变与竞技格局分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·python·计算机·spark·毕业设计·课程设计·wta网球
Sweet锦1 小时前
不调 Python,不装向量库:我用纯 Java 写了一套以图搜图引擎
java·人工智能·开源·图搜索
未来之窗软件服务1 小时前
Go 利器 GoReSym:剥离符号恢复 Go 二进制元数据—东方仙盟
开发语言·golang·仙盟创梦ide·东方仙盟
fpcc1 小时前
AI和大模型—JEV模型
人工智能
weixin_446260851 小时前
面向演进式企业AI智能体技能的持续流程级评估
人工智能
言乐61 小时前
Python区分广度优先深度优先宽度优先的区别
python·算法·深度优先·广度优先·宽度优先
量子-Alex1 小时前
【大模型后训练SFT】Finetuning with Sampling: SFT Learns Better Than You Think
人工智能·深度学习·机器学习
ForDreamMusk1 小时前
Transformer Encoder Block
人工智能·深度学习·transformer