笔记整理自:

  1. https://my.oschina.net/leejun2005/blog/145911
  2. https://zhuanlan.zhihu.com/p/25221086
  3. https://docs.python.org/3/library/copy.html
    4.https://zhuanlan.zhihu.com/p/54011712

(强烈推荐看最后一个)

赋值操作

只是复制了新对象的引用,不会开辟新的内存空间。
python的赋值语句是建立对象的引用而不是复制对象,创建的是局部变量,例如:

list_a = []
def a():
    list_a = [1]      ## 语句1
a()

在函数中赋值并不会改变全局变量的值,输出值为[]

values = [0, 1, 2]
values[1] = values

此时values的值为[0, [...], 2],其中values[1]是无限循环的值,因为创建了自身的引用。
正确的做法应当是:

values[1] = values[:]

list的[:]操作其实是浅拷贝。

浅拷贝与深拷贝

浅拷贝:A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.创建新对象,其内容是原对象的引用。有三种浅拷贝的形式:切片操作,工厂函数,copy操作
浅复制要分两种情况进行讨论:

1)当浅复制的值是不可变对象(字符串、元组、数值类型)时和“赋值”的情况一样,对象的id值(id()函数用于获取对象的内存地址)与浅复制原来的值相同。

2)当浅复制的值是可变对象(列表、字典、集合)时会产生一个“不是那么独立的对象”存在。有两种情况:

第一种情况:复制的对象中无复杂子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。

第二种情况:复制的对象中有复杂子对象(例如列表中的一个子元素是一个列表),如果不改变其中复杂子对象,浅复制的值改变并不会影响原来的值。 但是改变原来的值中的复杂子对象的值会影响浅复制的值。

深拷贝:A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。

Python的可变与不可变对象

不可变对象:int, float, long, str, tuple
可变对象:list, set, dict等

>>> a = 'xianglong.me'
>>> id(a)
140443303134352
>>> a = '1saying.com'
>>> id(a)
140443303131776
def func_int(a):
    a += 4
t = 0
func_int(t)
print t
# output: 0

对于不可变对象,每一次操作都会创建一个新值,把变量绑定到新的对象上,旧的值没有被引用就等待垃圾回收。a是t的对象的新引用,修改不可变对象后,a会指向新的对象,但是不会改变旧的对象,所以t不变。但是如果传入的是可变对象的引用,就可以更改对象的值。

>>> a_list = [1, 2, 3]
>>> id(a_list)
140443302951680
>>> a_list.append(4)
>>> id(a_list)
140443302951680

对于可变对象,操作不会改变地址。

标签: none

添加新评论