ZetCode

Python id 函数

上次修改时间:2025 年 4 月 11 日

这篇全面的指南探讨了 Python 的 id 函数,该函数返回对象的标识。我们将涵盖对象标识、内存地址以及 Python 中对象识别的实际示例。

基本定义

id 函数返回对象的标识。这是一个在对象的生命周期内唯一的整数常量。在 CPython 中,它表示对象的内存地址。

关键特性:返回一个整数,在对象的生命周期内是唯一的,相同对象的值相同,不同对象的值不同。该值依赖于实现,但在 CPython 中是一致的。

简单对象的基本用法

这是一个使用不同 Python 对象的简单用法,展示了 id 如何为每个对象返回唯一的标识符。

basic_id.py
x = 42
y = "hello"
z = [1, 2, 3]

print(id(x))  # Unique identifier for integer 42
print(id(y))  # Unique identifier for string "hello"
print(id(z))  # Unique identifier for list [1, 2, 3]

这个例子展示了 id 如何用于不同的对象类型。每个对象都会获得一个在其生命周期内保持不变的唯一标识符。

实际数字在运行之间会有所不同,但对于同一对象,在单个程序执行期间将保持一致。

使用 is 运算符进行身份比较

id 函数与 Python 的 is 运算符密切相关。这个例子演示了它们之间的关系。

identity_comparison.py
a = [1, 2, 3]
b = a
c = [1, 2, 3]

print(a is b)          # True (same object)
print(id(a) == id(b))  # True (same id)
print(a is c)          # False (different objects)
print(id(a) == id(c))  # False (different ids)

该示例表明 is 检查对象身份,这相当于比较 id 值。a is b 为 True,因为它们引用同一个对象。

即使 ac 包含相同的值,它们也是具有不同标识的不同对象。

小整数缓存

Python 缓存小整数以进行优化。这会影响它们的身份行为,如本例所示。

int_caching.py
x = 256
y = 256
print(x is y)      # True (cached)
print(id(x) == id(y))  # True

a = 257
b = 257
print(a is b)      # False (not cached)
print(id(a) == id(b))  # False

Python 缓存 -5 到 256 之间的整数。对于这些值,多个引用将指向同一个对象,从而导致相同的 id 值。

对于较大的整数(如 257),每次赋值都会创建一个具有不同标识的新对象,除非显式别名。

可变与不可变对象

id 的行为在可变对象和不可变对象之间有所不同。这个例子演示了这些差异。

mutable_immutable.py
# Immutable string
s1 = "hello"
s2 = "hello"
print(id(s1) == id(s2))  # True (may be interned)

# Mutable list
lst1 = [1, 2, 3]
lst2 = [1, 2, 3]
print(id(lst1) == id(lst2))  # False (always different)

# Modified mutable object
print(id(lst1))  # Before modification
lst1.append(4)
print(id(lst1))  # After modification (same id)

如果不可变对象(如字符串)具有相同的值,它们可能共享相同的标识(由于字符串驻留)。可变对象始终具有不同的标识。

修改可变对象不会更改其标识,因为对象本身保持不变,只是其内容发生变化。

自定义对象和身份

自定义类实例具有唯一的标识,类似于内置对象。此示例显示了自定义对象的身份行为。

custom_objects.py
class Person:
    def __init__(self, name):
        self.name = name

p1 = Person("Alice")
p2 = Person("Alice")
p3 = p1

print(id(p1))  # Unique identifier for p1
print(id(p2))  # Different identifier for p2
print(id(p3))  # Same as p1 (alias)

print(p1 is p3)  # True
print(p1 is p2)  # False

自定义类的每个新实例都会获得一个唯一的身份。别名对象 (p3 = p1) 会创建一个对同一对象的引用,该对象具有相同的身份。

即使具有相同的属性值,p1 和 p2 也是具有不同标识的不同对象。

最佳实践

资料来源

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有 Python 教程