🐍 Day 2 :Python 变量与数据类型 — 一切皆对象

学习路径:Python_AIGC · Day 2

理解 Python 的「变量」本质是标签,以及核心数据类型的正确使用姿势。


1️⃣ 变量本质:名字贴在对象上

与其他语言不同,Python 变量不是盒子,是标签

python 复制代码
a = [1, 2, 3]
b = a          # b 和 a 指向同一个 list 对象
b.append(4)
print(a)       # [1, 2, 3, 4] --- a 也被改了!

🖼️ 内存模型ab 都是贴在 [1,2,3] 对象上的标签。修改对象内容,所有标签都看到变化。

id() --- 对象的身份证

每个 Python 对象创建后都有一个唯一的身份标识,id() 返回的就是这个值。在 CPython 里就是对象的内存地址。

python 复制代码
a = [1, 2, 3]
b = a
c = [1, 2, 3]

print(id(a))   # 139824567890123
print(id(b))   # 139824567890123 --- b 是 a 的标签,同一对象
print(id(c))   # 139824568901234 --- c 是新对象,地址不同

# is 运算符底层就是比较 id()
print(b is a)  # True  → id(b) == id(a)
print(c is a)  # False → id(c) != id(a)
print(c == a)  # True  → 值相等(逐元素比较)

小整数缓存 --- 实现细节别依赖

CPython 启动时会预创建 -5256含边界 )的小整数对象并复用。但这个行为在交互式环境(REPL)函数/代码块内表现不一致:

python 复制代码
# REPL 中逐行输入:
x = 256
y = 256
print(x is y)   # True --- 在缓存范围内

x = 1000
y = 1000
print(x is y)   # False --- 超出缓存,每行独立编译,不同对象
print(x == y)   # True --- 值相等

# 但写在同一个函数/代码块里:
def test():
    a = 1000
    b = 1000
    print(a is b)  # ⚠️ 可能是 True!CPython 常量折叠优化

test()

结论:永远不要用 is 比较整数或字符串的值。is 只该用在一个场景------

python 复制代码
# ✅ 唯一正确的 is 用法:判 None
result = some_function()
if result is None:   # ✅ 正确,None 是全局单例
    pass
if result == None:   # ❌ 不要这样写,虽然结果一样但语义不对
    pass

2️⃣ 核心类型速览

类型 可变 示例 说明
int 42, 0xFF, 0b1010 任意精度
float 3.14, 1e-5 双精度浮点
str "hello", f"val={x}" Unicode 字符串
bool True, False isinstance(True, int) → True
NoneType None 单例,用 is 判断
bytes b"abc", bytes([65,66]) 原始字节
list [1, 2, 3] 有序可变序列
dict {"a": 1} 哈希表映射
set {1, 2, 3} 无序不重复集合
tuple (1, 2), 1, 2 不可变序列

3️⃣ 类型转换 --- 显式大于隐式

python 复制代码
# 显式转换(推荐)
s = "42"
n = int(s)          # str → int
pi = float("3.14")   # str → float
text = str(100)      # int → str

# 容器转换
list("hello")   # → ['h','e','l','l','o']
set([1,2,2,3])  # → {1, 2, 3}
tuple([1,2,3])  # → (1, 2, 3)

# 类型检查
isinstance(42, int)         # True
isinstance("hi", (str, int)) # True --- 多个类型

隐式转换陷阱

python 复制代码
# ❌ 隐式转换可能出问题
result = "The answer is " + 42      # TypeError!
result = "The answer is " + str(42)  # ✅

# ⚠️ 浮点精度
0.1 + 0.2 == 0.3  # False! 0.30000000000000004

# 用 Decimal 处理精度敏感场景
from decimal import Decimal
Decimal("0.1") + Decimal("0.2") == Decimal("0.3")  # True

4️⃣ 深浅拷贝 --- 区分复制标签 vs 复制对象

python 复制代码
import copy

original = [[1, 2], [3, 4]]

# ❌ 只是拷贝标签
wrong = original

# 浅拷贝:新容器,但元素是同一引用
shallow = copy.copy(original)
shallow[0].append(99)
print(original)   # [[1, 2, 99], [3, 4]] --- 内层也变了!

# 深拷贝:递归复制所有对象
deep = copy.deepcopy(original)
deep[0].append(999)
print(original)   # [[1, 2, 99], [3, 4]] --- 不受影响

常用数据类型的浅拷贝方式

python 复制代码
# list
a.copy()         # 或 a[:]
# dict
b.copy()         # 或 dict(b)
# set
c.copy()         # 或 set(c)

5️⃣ 实用技巧

f-string 格式化

python 复制代码
name = "Python"
ver = 3.12
print(f"{name} {ver}")          # Python 3.12
print(f"{name:>10}")            # 右对齐:    Python
print(f"{ver:.2f}")             # 3.12
print(f"{1024:b}")              # 二进制:10000000000
print(f"{1024:#x}")             # 十六进制:0x400

动态类型但静态检查

python 复制代码
# Python 动态类型
def add(a, b):
    return a + b

# 写类型标注供 mypy/pyright 检查
def add(a: int, b: int) -> int:
    return a + b

⚠️ 避坑总结

原因 解法
修改列表影响了其他变量 变量是标签 可变对象用 copydeepcopy
1.1 + 2.2 != 3.3 浮点精度 金额用 Decimal,比较用容差
is 比整数/字符串失灵 缓存/常量折叠不可靠 数值和字符串只用 ==is 只判 None
函数默认参数是可变对象 默认值只创建一次 None + 函数内初始化

📝 今日小结

  • ✅ 变量是标签,== 判值,is 判身份
  • ✅ 核心类型分类:可变 vs 不可变
  • ✅ 显式类型转换,警惕浮点精度
  • ✅ 深浅拷贝的区别和使用场景
相关推荐
Csvn1 小时前
📊 SQL 入门 Day 17:数据更新与删除
后端·sql
秋天的一阵风1 小时前
🔥 Network 里那坨 "data:" 我真看吐了,自制开源 Chrome 插件,AI 流式调试直接开挂
前端·人工智能·后端
IT_陈寒2 小时前
Python的GIL让我深夜加班,这破锁到底怎么折腾的
前端·人工智能·后端
覆东流2 小时前
2.Java程序基础
java·开发语言·后端
ttwuai2 小时前
Go 后台定时任务启停不生效怎么办?先查调度同步链路
开发语言·后端·golang
AINative软件工程3 小时前
LLM 应用的 Feature Flag 工程实践:Prompt、模型与 AI 行为的生产安全灰度
后端·llm·ai编程
weixin_431600443 小时前
前端对接 SSE 的两种常见方式
前端·后端·学习·ai·sse·nest.js
Larcher9 小时前
React Router 不只是页面跳转:从 SPA 路由到权限守卫的完整实践
javascript·后端
Larcher9 小时前
大模型为什么每次回答都不一样?一文搞懂 Temperature、Top K 与 Top P
javascript·后端