讲讲Python小整数池背后的真实

在Python中,整数对象的复用涉及两个层面:

第一层是小整数池(small integers pool)1机制。Python会预先缓存一定范围内的整数对象(通常是[-5, 256]),这个范围内的整数总是会复用同一个对象。比如:

a = 256
b = 256
print(a is b)  # True,因为256在小整数池范围内

第二层是Python解释器的编译优化。当Python将源代码编译成字节码时,如果发现同一个编译单元(compilation unit)中有相同的字面量,会尝试复用它们。但这种优化的行为会因执行环境而异:

  1. .py文件中,整个文件是一个编译单元:

    x = 257
    y = 257
    print(x is y)  # 输出True,因为编译器对整个文件进行了优化
    
  2. 在REPL环境中,每一行输入都是独立的编译单元:

    >>> x = 257  # 第一个编译单元
    >>> y = 257  # 第二个编译单元
    >>> x is y   # 输出False,因为是在不同的编译单元中创建的对象
    

    我们可以用exec()来模拟REPL的这种行为:

    namespace = {}
    exec("x = 257", namespace)  # 相当于一个独立的编译单元
    exec("y = 257", namespace)  # 另一个独立的编译单元
    exec("print(x is y)", namespace)  # 输出False
    

这个行为提醒我们:

  1. 不要依赖Python的对象复用机制编写代码,因为它是实现细节,可能随版本变化
  2. 使用is运算符时要格外小心,它比较的是对象的身份(identity),而不是值
  3. 如果要比较值是否相等,应该使用==运算符:
    x = 257
    y = 257
    print(x == y)  # 始终为True,因为比较的是值而不是身份
    

这里还有个有趣的实验可以帮助理解:

# 在同一行定义的变量会复用对象
>>> x, y = 257, 257
>>> x is y
True

# 在不同行定义的变量会创建新对象
>>> x = 257
>>> y = 257
>>> x is y
False

# 但如果使用同一个表达式,也会复用对象
>>> y = x = 257
>>> x is y
True

这进一步说明了Python解释器的优化行为:当它能够在编译时确定多个变量会被赋予相同的字面量值时,就会尝试复用对象。但如果是在REPL环境下分行输入,每行都是独立的编译单元,就不会发生这种优化。


  1. 短字符串同理 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值