agent01-Python补足

实验 · W1-Day1-2-名字绑定与可变性

W1-Day1-2-名字绑定与可变性

"""W1 · Day 1-2 实测:名字绑定、对象模型、可变性

跑法(uv 工程要到 Day 6 才建,此时用裸 python;-W error 是零告警验收要求):
    python -X utf8 -W error "docs/01-Python补足/产出/实验/W1-Day1-2-名字绑定与可变性.py"

本文件只放代码。完整讲解见配套课件 docs/01-Python补足/课件/同名 .md
(D34:课件与实验脚本同名配对,缺一视为该次课没上);
沉淀出的语义差异条目落到 docs/01-Python补足/产出/差异清单-C++到Python.md。
"""

import copy

# --- 1. 赋值 = 给对象贴新名字,不是拷贝 -----------------------------------
a = [1, 2]
b = a
b.append(3)
print("1) 改 b 之后 a =", a, "| a is b =", a is b)

c = list(a)
c.append(99)
print("1) 改 c 之后 a =", a, "| a is c =", a is c)


# --- 2. 实参传递:call by object reference --------------------------------

def mutate(p):
    p.append("被改了")


def rebind(p):
    p = ["新对象"]


def replace_in_place(p):
    p[:] = ["整块替换"]


xs = ["原始"]
mutate(xs)
print("2) mutate 之后      xs =", xs)

rebind(xs)
print("2) rebind 之后      xs =", xs)

xs2 = ["a"]
replace_in_place(xs2)
print("2) p[:] = ... 之后 xs2 =", xs2)


# --- 3. is 是身份比较,== 是值比较 ----------------------------------------

like = [1, 2]
same = [1, 2]
print("3) 内容相同的两个列表:is =", like is same, "| == =", like == same)

x = 257
y = 257
print("3) 同一个 code object 里的 257(常量池去重)→ x is y =", x is y)

ns1, ns2 = {}, {}
exec(compile("X = 257", "<m1>", "exec"), ns1)
exec(compile("X = 257", "<m2>", "exec"), ns2)
print("3) 两个独立代码对象里的 257:is =", ns1["X"] is ns2["X"])

print("3) 小整数缓存 [-5, 256]:id(256) == id(256) →", id(256) == id(256))
print("3) 可变对象不缓存:      [] is [] →", [] is [])


# --- 4. 可变默认参数陷阱 --------------------------------------------------

def collect_bad(item, acc=[]):
    acc.append(item)
    return acc


print("4) collect_bad(1/2/3) =",
      collect_bad(1), collect_bad(2), collect_bad(3))
print("4) collect_bad.__defaults__ =", collect_bad.__defaults__)


def collect_ok(item, acc=None):
    if acc is None:
        acc = []
    acc.append(item)
    return acc


print("4) collect_ok(1/2/3)  =",
      collect_ok(1), collect_ok(2), collect_ok(3))


# --- 5. 浅拷贝 vs 深拷贝 --------------------------------------------------

inner = [1, 2]
src = {"k": inner}
print("5) 初始             src =", src)

shallow = copy.copy(src)
shallow["k"].append(99)
print("5) 浅拷贝改内层后   src =", src)

deep = copy.deepcopy(src)
deep["k"].append(100)
print("5) 深拷贝改内层后   src =", src)
print("5) 深拷贝改内层后  deep =", deep)

print("5) 浅拷贝的内层是同一个对象吗:", copy.copy(src)["k"] is src["k"])


# --- 6. tuple 不等于「完全不可变」 ----------------------------------------

t = (1, [2, 3])
t[1].append(4)
print("6) t[1].append(4) 之后 t =", t)

try:
    t[1] += [5]
except TypeError as e:
    print("6) t[1] += [5] 抛:", type(e).__name__, "-", e)
print("6) 异常之后 t =", t)

try:
    hash(t)
except TypeError as e:
    print("6) hash(t) 抛:", type(e).__name__, "-", e)