如何理解Python文档中‘不可变对象直接引用的对象集合不可变’?
Great question—this is one of the trickiest nuances of Python's immutability, so you're not alone in scratching your head over it! Let's break this down with clear examples and plain language.
First, let's restate the official Python docs quote to anchor our discussion:
不可变序列类型的对象创建后无法更改。(若该对象包含对其他对象的引用,这些对象可能是可变的并可被修改;但不可变对象直接引用的对象集合不可变。)
What Does "Directly Referenced by an Immutable Object" Mean?
Think of an immutable object (like a tuple or string) as a locked box. Inside this box are slots that hold direct pointers (references) to other objects. The phrase "directly referenced objects" refers to the collection of objects those slots point to.
For example:
- A tuple
my_tuple = (["apple"], "banana")has two direct references: one to a list object, and one to a string object. - A string
"hello"has direct references to individual character code points (though in Python, strings are handled as single units, the analogy holds).
Why Is This Collection of Direct References Immutable?
The "locked box" analogy holds here: you can't rearrange, add, remove, or replace the slots inside the immutable object. In other words:
- You can't replace a direct reference in the tuple (e.g.,
my_tuple[0] = ["orange"]will throw aTypeError). - You can't append a new reference to the tuple (e.g.,
my_tuple.append("cherry")won't work). - You can't delete a reference from the tuple (e.g.,
del my_tuple[1]is invalid).
This is exactly what the docs mean when they say "the collection of objects directly referenced by an immutable object is immutable."
But Wait—What About Mutable Objects Inside?
Here's the key distinction: the locked box prevents you from changing which objects it points to, but if an object inside the box is mutable (like a list or dictionary), you can still modify that object's internal state.
Let's use code to see this in action:
# Create an immutable tuple holding mutable lists locked_box = ([1, 2], [3, 4]) # Try to replace a direct reference (this fails!) try: locked_box[0] = [5, 6] except TypeError as e: print(f"Error when replacing reference: {e}") # Output: Error when replacing reference: 'tuple' object does not support item assignment # Modify the internal state of a mutable object inside (this works!) locked_box[0].append(5) print(f"Modified tuple: {locked_box}") # Output: Modified tuple: ([1, 2, 5], [3, 4])
Notice that the tuple itself still references the exact same two list objects as before—we didn't change the collection of direct references. We only changed what's inside one of those lists.
Quick Recap
- An immutable object's direct reference collection is fixed: you can't add/remove/replace the objects it points to directly.
- If those direct references point to mutable objects, you can still modify the mutable objects' internal data—this doesn't violate the immutability of the parent object.
内容的提问来源于stack exchange,提问作者ig-melnyk

