Python 3中两个实例的属性指向同一内存地址的原因探究
为什么IPython中k1.a和k2.a会指向同一内存地址?
嘿,这个问题核心在于Python的对象驻留优化,再加上IPython交互环境的额外加持,我给你一步步说清楚:
1. Python内置的不可变小对象驻留机制
Python为了节省内存、提升性能,会对一些常用的不可变对象做「驻留(interning)」处理:
- 比如**-5到256之间的整数**,Python会提前把这些整数对象创建好,放在一个全局的对象池里。不管你在代码里多少次赋值
x=100,拿到的都是同一个对象的引用。 - 还有符合规则的短字符串(比如不含特殊字符的短字符串),也会被自动驻留,比如
"hello"这种字符串,多次赋值也会指向同一个内存地址。
因为这些对象是不可变的,多个引用指向同一个对象完全安全——你没法修改整数100本身的值,所以Python放心共享它们的引用。
2. IPython的额外优化
普通Python解释器的驻留规则已经存在,但IPython在交互环境中做了更激进的缓存优化:
- 它会对更多类型的不可变对象进行驻留,哪怕是超出-5到256范围的整数,或者更长的字符串,只要在同一个IPython会话中出现过相同值的对象,就可能被复用引用。
- 这是IPython为了提升交互体验、减少重复对象创建开销特意做的优化,所以在IPython里你会看到比普通Python更多的「同一引用」情况。
3. 可变对象不会有这个情况
如果你的a是可变对象(比如列表[]、字典{}),那k1.a和k2.a肯定是不同的对象,因为Python绝不会对可变对象做驻留——毕竟可变对象的值可以被修改,共享引用会导致意想不到的副作用。举个例子:
class K: pass k1 = K() k2 = K() k1.a = [1,2,3] k2.a = [1,2,3] print(k1.a is k2.a) # 输出False,二者是不同对象
内容的提问来源于stack exchange,提问作者c00der
相关产品推荐
相关产品推荐

