python 深拷贝与浅拷贝以及list.append( self )

本文探讨了Python中变量引用的工作原理,展示了不同类型的拷贝(浅拷贝与深拷贝)的效果,并通过实例说明了它们的区别。同时,还讨论了一个有趣的list自我追加现象及其背后的原因。

#Python3.2

例子:

l = list('abc')
a = l
a.append('d')
print(l)
l.append('e')
print(a)
l = list('abcde')
print(id(l))
print(id(a))

可见,a = l 即将 a 作为 l 的引用,类似于 C 语言中 &  ;如果重新生成一个 l ,即使内容一致,id 也已经变化了,由于引用计数的原因,a 这个变量名仍然能找到它所指代的对象,不会迷失;

Python标准库中有个 copy 模块,用于对象之间的拷贝,其中常用的两个函数:copy 和 deepcopy;

copy.copy() 是浅拷贝,只拷贝了父对象,不会拷贝父对象中的子对象;deepcopy 是深拷贝,可以认为是完全的复制过去了;

l = ['a', 'b', 'c', [1, 2, 3]]
import copy
a = copy.copy(l)
b = copy.deepcopy(l)
a.append('e')
b.append('f')
print(a, b, l)
a[3][2] = 'x'
b[3][2] = 'y'
print(a, b, l)

可见,浅拷贝后,父对象中的子对象,即上例中列表中的列表,还是被共享着的;


对于一个 list 对象

l = ['a', 'b', 'c']

如果
l = l.append(l)

会得出一个很有意思的结果:
>>l
>>['a', 'b', 'c', [...]]

如果:
a = l[4]
a == l
a is l

结果都是 True;

对于上述的例子中的 l, len(l) 是 5;如果  

l = l.extend(l)

则不会出现这种效果
Python 中,类的结构和对象的行为有时可能会导致一些令人困惑的结果,尤其是在使用可变类型(如列表)作为类变量时。以下是对这一问题的深入分析以及相关用法。 ### 类变量实例变量的区别 在定义类时,如果将一个列表直接赋值给类属性,该属性会成为所有实例共享的类变量。例如: ```python class Example: shared_list = [] # 类变量 obj1 = Example() obj2 = Example() obj1.shared_list.append(1) # 修改的是类变量 print(obj2.shared_list) # 输出: [1] ``` 在这种情况下,`shared_list` 是 `Example` 类的一个属性,而不是单个实例的属性。因此,当通过任意一个实例修改这个列表时,所有实例都会看到这个变化,因为它们引用的是同一个对象[^1]。 ### 实例变量的正确使用方式 为了避免这种意外行为,通常建议将列表定义为实例变量,这样每个实例都会有自己独立的副本: ```python class Example: def __init__(self): self.instance_list = [] # 实例变量 obj1 = Example() obj2 = Example() obj1.instance_list.append(1) print(obj2.instance_list) # 输出: [] ``` 此时,`instance_list` 是每个实例独有的,对它的修改不会影响到其他实例。 ### 类变量实例变量的访问机制 当访问一个对象的属性时,Python 首先会在该对象的实例字典中查找该属性,如果找不到,则会去类的字典中查找。因此,当尝试修改类变量时,如果不小心,可能会导致意料之外的行为: ```python class Example: counter = 0 obj1 = Example() obj2 = Example() obj1.counter += 1 # 这实际上是创建了一个实例变量 counter print(obj1.counter) # 输出: 1 print(obj2.counter) # 输出: 0 ``` 在这个例子中,`obj1.counter += 1` 并没有修改类变量 `counter`,而是为 `obj1` 创建了一个新的实例变量 `counter`。 ### 使用类方法操作类变量 如果确实需要在类级别上维护一个列表,并且希望多个实例能够共享并修改它,可以通过类方法来操作: ```python class Example: shared_list = [] @classmethod def add_item(cls, item): cls.shared_list.append(item) obj1 = Example() obj2 = Example() obj1.add_item(1) print(obj2.shared_list) # 输出: [1] ``` 这种方式可以明确地控制类变量的修改逻辑,同时避免了直接访问类变量可能引发的问题。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值