Python中的可变和不可变对象以及赋值、浅拷贝和深拷贝对比分析

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

在Python中,对象可以分为不可变(immutable)对象和可变(mutable)对象。这是关于对象在内存中如何管理和修改的概念。理解对象的可变性对于编写有效且可预测的Python代码非常重要。当您需要在函数之间传递参数或处理数据时,了解对象是否是不可变的或可变的将有助于避免意外副作用。不可变对象通常更容易推断其行为,因为它们不会在不经意间发生更改,而可变对象则需要更多的谨慎。

不可变对象(Immutable Objects)

不可变对象是指一旦创建,就不能被更改的对象。任何尝试修改不可变对象的值都将创建一个新的对象。常见的不可变对象包括整数(int)、浮点数(float)、字符串(str)、元组(tuple)等。不可变对象通常具有更高的内存效率,因为它们不需要在内存中保留额外的空间来处理修改。这也使得它们在哈希表等数据结构中很有用。

代码示例:

x = 5
y = x  # y引用与x相同的不可变对象
x = 10  # 创建一个新的对象,x现在引用新的不可变对象,y仍然引用旧对象(5)

可变对象(Mutable Objects)

可变对象是指在创建后仍然可以修改其值的对象。修改操作不会创建新的对象,而是直接在原对象上进行更改。常见的可变对象包括列表(list)、字典(dict)、集合(set)等。可变对象的修改可能需要更多的内存和处理时间,因为它们允许在原地修改,而不是创建新的对象。

代码示例:

my_list = [1, 2, 3]
my_list.append(4)  # 直接在原列表上添加元素
# my_list仍然引用同一个可变对象,其值现在为[1, 2, 3, 4]

Python中的赋值、浅拷贝和深拷贝对比分析

不可变对象(Immutable Objects)

Python 内不可变对象的内存管理方式是引用计数,所以 无论是赋值、前拷贝还是深拷贝,Python 不会对值相同的不可变对象,申请单独的内存空间,只会记录它的引用次数。

a = "marcos"
b = a
c = copy.copy(a)
d = copy.deepcopy(a)

print("原值:%d" % id(a))
print("赋值:%d" % id(b))
print("浅拷贝:%d" % id(c))
print("深拷贝:%d" % id(d))

输出:

原值:1885360472840
赋值:1885360472840
浅拷贝:1885360472840
深拷贝:1885360472840

但对不可变对象进行修改时,实际上是让变量指向了一个新的对象(对象的地址重新分配)。

可变对象(Mutable Objects)

赋值是引用对象的地址,不会分配新的地址,浅拷贝和深拷贝均会为复制对象分配新的内存空间。

但是,对于可变对象内的可变元素和不可变元素,发生浅拷贝和深拷贝时存在区别:
(1)当对原对象浅拷贝时,原对象内可变对象的对应元素的改变,复制对象的对应元素也相应改变,而不可变元素不会随着原对象元素的改变而改变;
(2)当对原对象深拷贝时,无论原对象的元素如何发生变化,复制对象的对应元素均不发生变化。

import copy

a = [[0],"zhangsan"]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)

print("原值地址:%d" % id(a))
print("赋值地址:%d" % id(b))
print("浅拷贝地址:%d" % id(c))
print("深拷贝地址:%d" % id(d))

a[0][0] = 1
a[1] = "lisi"

print("原值:",a)
print("赋值:",b)
print("浅拷贝:",c)
print("深拷贝:",d)

print("原值地址:%d" % id(a))
print("赋值地址:%d" % id(b))
print("浅拷贝地址:%d" % id(c))
print("深拷贝地址:%d" % id(d))

输出:

原值地址:1724350537608
赋值地址:1724350537608
浅拷贝地址:1724350569544
深拷贝地址:1724350587336
原值: [[1], 'lisi']
赋值: [[1], 'lisi']
浅拷贝: [[1], 'zhangsan']
深拷贝: [[0], 'zhangsan']
原值地址:1724350537608
赋值地址:1724350537608
浅拷贝地址:1724350569544
深拷贝地址:1724350587336

附:更多的示例

clone函数

下列程序,只是把x的索引赋值给y,并没有给y分配内存空间,当改变y时,x也发生改变。

x = torch.arange(6).reshape((2,3))
y = x
y[:] = 2

下列程序,为y分配了内存空间,改变y时并不改变x的值。

x = torch.arange(6).reshape((2,3))
y = x.clone()
y[:] = 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI Player

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值