问题1: 将列表c
添加到列表a,b
之中,修改c
中的值,a,b
会变化吗?
a = list()
b = list()
c = [2,3]
a.append(c)
b.append(c)
print(a,b)
输出:[[2, 3]] [[2, 3]]
#修改C中第一个元素
c[0] = 1
print(a,b)
输出1:[[1, 3]] [[1, 3]]
,即改变c
中元素,a,b
也发生了变化
分析1
a,b,c
都是容器类对象,当将一个容器A放到另外一个容器B里的时候,B中放的是A的引用,即A的地址。所以改变c
,也会改变a,b
问题2:将变量d
添加到列表a,b
之中,改变d
,a,b
会变吗?
d = 9
a.append(d)
b.append(d)
print(a,b)
输出:[[1, 3], 9] [[1, 3], 9]
#改变d的值,考虑一下 a,b会变吗?
d = 10
print(a,b)
输出2:[[1, 3], 9] [[1, 3], 9]
,即改变d
,a,b
没有变化
分析2
d
是数值类型,a,b
是容器类型,将d
放到(append)a,b
中,a,b
之中保存了d
的引用,但是改变d
的值,会重新分配一块内存空间,也就是说前后两个d
,已经没有任何关系了。这样说可能不太好懂,我们看下面的列子:
a = 10
print(id(a))
a = 11
print(id(a))
#输出:
4544079472
4544079504
可见,只改变a
的值,a
的地址也发生了变化,即前后两个a
,没有任何关系了。另外:前一个a
如果没有其他对象引用的话,将会被回收。
python 数据类型
Python有五个标准的数据类型:
- Numbers(数字)
- String(字符串)
- List(列表)
- Tuple(元组)
- Dictionary(字典)
其中,1,2
代表数字常量或者字符串常量,常量表示不可以改变,如果想改变就要创建新的对象。如分析2
所示。3,4,5
代表容器类对象,存储的是常量引用或是其他容器的引用,修改他们区别,如上问题1,2所示。
字典的例子
下面是基于字典容器的例子,结论和上面的例子相同。
f = [1,2,3]
g = 10
#打印 f,g地址
print(f'g:{id(g)} f:{id(f)}')
d = {'one':g,'two':f}
#打印字典中对应的地址
print(f"d['one']:{id(d['one'])} d['two']: {id(d['two'])}")
输出:
g:4392810096 f:4436990920
d['one']:4392810096 d['two']: 4436990920
f[1] = 20 #改变f中某个元素
g = 20 #改变g的值(注意创建了新的对象)
print(f"新g地址:{id(g)}, 字典中旧g地址:{id(d['one'])}")
print(d)
输出:
新g地址:4392810416, 字典中旧g地址:4392810096
{'one': 10, 'two': [1, 20, 3]}
python 中的copy和deepcopy
copy: 即shallow copy,容器中的常量换新,容器中的容器保留了引用。
deepcopy:容器中的所有内容全部换新。
举个栗子:
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象
b = a #赋值,传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝
a.append(5) #修改对象a
a[4].append('c') #修改对象a中的['a', 'b']数组对象
print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
输出结果:
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]