0%

Python 中的可变对象与不可变对象

Python 中只存在 “引用传递” 这一种传递方式, 准确来说应该是指针传递 , 通过 id() 函数可以确定,参数传入前和传入后的地址值一样

所谓的对象可变与不可变,其实是看是否提供了修改自身对象的方法

变量无类型,对象有类型

不可变 (immutable) 对象类型 (指针地址不可变)

  • int
  • float
  • decimal
  • complex
  • bool
  • str
  • tuple
  • range
  • frozenset
  • bytes

可变 (mutable) 对象类型

  • list
  • dict
  • set
  • bytearray

user-defined classes (unless specifically made immutable)

Python 中的对象类型分为 可变类型不可变类型

例如: Python 中的数字是不可变类型

1
2
3
4
5
6
7
8
9
10
11
a = 2    # 变量 a 指向一个 Number 对象
b = 2 # 变量 b 和 a 指向同一个 Number 对象 此时 id(a) == id(b)
a = 1 # 变量 a 指向一个新的 Number 对象, 而并不是 a 原本指向的 Number 对象发生了改变! 此时 id(a) != id(b)

# 同样, 函数参数传递时也是如此
def add(num):
print(id(num)) # 第一次打印的 id 是与外部的参数的 id 一致 (引用传递, 准确来说是指针传递)
num += 2 # 改变了 num 指向的对象, id(num) 发生了改变, 但不影响外部传入变量的地址
print(id(num))

add(a) # 传递变量 a 其实是“引用传递”, 也就是将 a 指向的内存地址传递了

即使对于可变类型,其实也是指针传递

1
2
3
4
5
6
7
8
9
10
11
12
13
def test(lst):
print(id(lst)) # 2263872110464
lst = [1, 2, 3]
print(id(lst)) # 2263872133184

if __name__ == '__main__':
l = [9, 8, 7]
print(id(l)) # 2263872110464
print(l) # [9, 8, 7]
test(l) # 函数中改变的
print(id(l)) # 2263872110464
print(l) # [9, 8, 7]

可变类型的 "可变", 体现在下面这种情况

1
2
3
4
5
6
7
8
9
10
11
12
13
def test(lst):
print(id(lst)) # 2389391376256
lst.append(33)
print(id(lst)) # 2389391376256

if __name__ == "__main__":
l = [9, 8, 7]
print(id(l)) # 2389391376256
print(l) # [9, 8, 7]
test(l)
print(id(l)) # 2389391376256
print(l) # [9, 8, 7, 33]

参考文章:

https://www.cnblogs.com/shiyublog/p/10809953.html