【Python】变量赋值与引用机制:探究对象的可变性

概述

在Python中,变量赋值的机制涉及到对象的引用和对象的可变性。变量名只是对象的引用,而不是直接存储数据。因此,变量ab赋值后的行为差异,取决于两个因素:

  1. 对象是否可变(Mutable/Immutable)。
  2. 修改操作的类型(直接修改对象内容,还是重新赋值变量)。

1. 不可变对象(Immutable Objects)

不可变对象的值一旦创建,就不能修改其内容,例如:

  • 整数(int
  • 字符串(str
  • 元组(tuple
  • 布尔值(bool)等。
  • 场景:修改变量的新赋值
    a = 5         # a指向整数对象5
    b = a         # b也指向同一个整数对象5
    
    a = 6         # 此时a指向新的整数对象6,但b仍指向5
    
    print(b)      # 输出5
    

    原因

  • 赋值操作 b = a 时,仅复制引用,使得 ab 都指向同一个对象(初始是5)。
  • a = 6 时,a 的引用被更新为指向新对象6,而 b 仍然指向原对象5。
  • 不可变对象无法被修改内容,只能重新创建新对象,因此 b 不会变化。

  • 场景:尝试直接修改对象内容(无效)
    a = "hello"   # a指向字符串"hello"
    b = a         # b也指向相同的字符串对象
    
    # 尝试修改字符串内容(但不可变对象不允许此操作)
    a[0] = "H"    # 报错:'str' object does not support item assignment
    

    结果:此操作根本无法执行,因为字符串是不可变的。


    2. 可变对象(Mutable Objects)

    可变对象的值可以在创建后被修改,例如:

  • 列表(list
  • 字典(dict
  • 集合(set
  • 自定义类实例等。
  • 场景:直接修改对象内容
    a = [1, 2]    # a指向列表[1, 2]
    b = a         # b指向同一个列表对象
    
    a.append(3)   # 修改列表内容,原列表变为[1, 2, 3]
    
    print(b)      # 输出[1, 2, 3]
    

    原因

  • ab 指向同一个列表对象。
  • append() 方法直接修改了该对象的内部内容,因此两个变量看到的都是同一个被修改后的对象。

  • 场景:修改变量的引用(不影响对方)
    a = [1, 2]
    b = a
    
    a = [3, 4]    # a的引用被更新为新列表[3,4],但b仍指向原列表[1,2]
    
    print(b)      # 输出[1, 2]
    

    原因

  • a = [3,4] 是一个新的赋值操作,直接改变了a的引用,使其指向新对象,而b未被修改,依然指向原列表。

  • 3. 核心总结

    情况 行为差异原因
    修改对象内容(可变对象) ab 指向同一个对象,修改内容会影响双方。
    直接重新赋值变量(任何对象) a 的引用指向新对象,而 b 的引用未变,因此 b 的值不受影响。
    尝试修改不可变对象的内容 不可变对象无法被修改,只能生成新对象,原对象的引用不会改变。因此 b 不变。

    4. 如何避免混淆

  • 不可变对象:赋值后的变量如果像“修改了 ab 不变”,这是因为实际是生成了新对象。
  • 可变对象:赋值后的变量如果像“修改了 ab 也变”,是因为两变量指向同一个对象,修改内容会影响双方。
  • 若希望二者独立

  • 对可变对象使用深拷贝或浅拷贝
    import copy
    b = copy.deepcopy(a)  # 完全独立的副本
    

  • 示例表格

    示例代码 是否修改对象内容 a 的值 b 的值
    a = 5; b = a; a = 6 6 5
    a = [1]; b = a; a[0] = 2 是(修改可变对象) [2] [2]
    a = [1]; b = a; a = [2] [2] [1]
    `a = “str”; b = a; a += “1” 否(生成新对象) "str1" "str"

    关键点:

  • 赋值是引用的复制b = a 仅让两个变量指向同一个对象。
  • 修改内容 vs 重新赋值
  • 修改内容:影响所有指向该对象的变量。
  • 重新赋值:仅修改当前变量的引用,不影响其他变量。
  • 作者:牛顿编程

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【Python】变量赋值与引用机制:探究对象的可变性

    发表回复