Python名称绑定(name binding)学习:求示例、应用场景及内部原理示意图
Python 名称绑定问题解答
1. 直观理解名称绑定原理的示例程序
以下示例可以清晰区分「名称绑定到同一对象」和「名称重新绑定」的差异,也是新手常踩的经典坑:
# 示例:名称绑定与对象修改的区别 a = [1, 2, 3] b = a # 名称b和a绑定到同一个列表对象 print(f"修改前a的内存id: {id(a)}") print(f"修改前b的内存id: {id(b)}") print(f"a和b是否指向同一对象: {a is b}") print(f"修改前列表值: a={a}, b={b}\n") # 仅修改绑定的列表对象本身,不改变绑定关系 b.append(4) print("修改列表对象内容后:") print(f"a和b是否指向同一对象: {a is b}") print(f"列表值: a={a}, b={b}\n") # 给b重新绑定新的列表对象,原绑定关系断开 b = [5, 6, 7] print("给b重新绑定新对象后:") print(f"a的内存id: {id(a)}") print(f"b的内存id: {id(b)}") print(f"a和b是否指向同一对象: {a is b}") print(f"列表值: a={a}, b={b}")
运行后可以看到:前半段a和b始终指向同一个对象,修改对象内容两个名称读取的结果同步变化;给b重新赋值后,b指向新的内存对象,和a完全脱离关联。
2. 实际开发中的典型应用场景
最常用的场景是理解Python函数参数的传递逻辑,Python所有参数传递本质都是传递对象的绑定关系,掌握名称绑定原理可以避免大量隐性bug:
def add_admin(user_list: list): # 直接修改形参绑定的列表对象本身,外部传入的原列表会同步变化 user_list.append({"name": "admin", "role": "super"}) # 如果写成 user_list = [{"name": "admin"}] 则是给形参重新绑定新对象,外部不受影响 origin_users = [{"name": "zhangsan", "role": "user"}] add_admin(origin_users) print(origin_users) # 输出:[{'name': 'zhangsan', 'role': 'user'}, {'name': 'admin', 'role': 'super'}]
开发中经常会遇到「函数内修改参数会不会影响外部值」的问题,判断依据就是看你是修改了绑定的对象本身,还是给形参重新做了绑定,完全基于名称绑定的逻辑。
3. 名称绑定变化过程示意图
Python中名称存储在栈帧的命名空间中,实际对象存储在堆内存中,箭头代表绑定关系,依次执行x=1、x=5、y=2、x=y的变化过程如下:
步骤1:执行 x = 1
名称x创建并绑定到堆内存中的整型对象1
【命名空间】 【堆内存】 +---------+ +-------+ | x |----->| 1 | +---------+ +-------+
步骤2:执行 x = 5
x断开与对象1的绑定,重新绑定到新的整型对象5,无引用的对象1会被垃圾回收
【命名空间】 【堆内存】 +---------+ +-------+ | x |----->| 5 | +---------+ +-------+ (对象1已回收)
步骤3:执行 y = 2
新增名称y,绑定到整型对象2
【命名空间】 【堆内存】 +---------+ +-------+ | x |----->| 5 | +---------+ +-------+ | y |----->| 2 | +---------+ +-------+
步骤4:执行 x = y
x断开与对象5的绑定,重新绑定到y指向的对象2,无引用的对象5会被垃圾回收
【命名空间】 【堆内存】 +---------+ +-------+ | x |---+ | 5 | (已回收) +---------+ | +-------+ | y |---+->| 2 | +---------+ +-------+
内容的提问来源于stack exchange,提问作者ladhee
相关产品推荐
相关产品推荐

