为什么要创造一个和列表差别不大的容器类型?
元组和列表看起来不同的一点是元组用圆括号而列表用方括号。而最重要的是,元组是不可变类型。这就保证了元组的安全性。
创造元组给它赋值和列表完全一样。除了一个元素的元组要在元组分割符里加一个逗号以防跟普通的分组操作符混淆。
>>> aTuple = (1) >>> aTuple 1 >>> aTuple = (1,) >>> aTuple (1,)
访问元组的值和列表也一样。
更新元组和更新字符串一样,要再构造一个新字符串,删除一个单独的元组元素以不可能的。只能显式地删除一整个元组,当然我们并不需要这么做。
元组和列表一样也没有自己专用的运算符和内建函数。因为元组本身是不可变的,所以这些操作对元组来说就是多余的,没有什么意义。
元组的特殊特性
元组的不可变导致我们不能改变其中的一个或多个元素,这样在我们传递数据给一个不了解的API时,可以保证我们的数据不会被修改。
而当我们需要操作从一个函数返回的元组时,可以用list()函数把它转换成一个列表。
元组的不可变也不是那么的不可变,我们可以像操作字符串一样连接、重复等等操作。还有是,虽然元组对象本身是不可变的,但是不代表它包含的可变对象是不可变的,比如说元组里存在数组:
>>> t = ([‘xyz‘, 123], 23, -103.4) >>> t ([‘xyz‘, 123], 23, -103.4) >>> t[0][1] 123 >>> t[0][1] = [‘abc‘, ‘def‘] >>> t ([‘xyz‘, [‘abc‘, ‘def‘]], 23, -103.4)
所有的多对象的,逗号分隔的,没有明确用符号定义的等等这些集合的默认类型都是元组。
>>> ‘abc‘, -4.24e93, 18+6.6j, ‘xyz‘ (‘abc‘, -4.24e+093, (18+6.6j), ‘xyz‘) >>> >>> x, y = 1, 2 >>> x, y (1, 2)
同样的,所有函数返回的多对象,不包括有符号封装的,都是元组。
作为字典的关键字
不可变对象的值不可变,意味着通过hash算法得到的值总是一个值。这是作为字典键值的必要条件。
拷贝Python对象
浅拷贝和深拷贝
浅拷贝的意思是创建一个和原对象一样的对象类型,其内容是原对象的引用。如下:
>>> person = [‘name‘, [‘savings‘, 100.0]] >>> hubby = person[:] >>> origin = [‘abc‘,[‘def‘,12.3]] >>> copy1 = origin[:] >>> copy2 = list(origin) >>> [id(x) for x in origin, copy1, copy2] [47106648, 47107008, 47104328] >>> [id(x) for x in origin[0], copy1[0], copy2[0]] [4172448, 4172448, 4172448]
而因为我们是在浅拷贝,改变其中一份拷贝并不会影响另一份
>>> copy1[0] = ‘change‘ >>> copy1 [‘change‘, [‘def‘, 12.3]] >>> copy2 [‘abc‘, [‘def‘, 12.3]]
与之相对的就是深拷贝:
>>> origin = [‘abc‘,[‘def‘,12.3]] >>> copy1 = origin >>> copy2 = origin >>> copy1[0] = ‘change‘ >>> copy1 [‘change‘, [‘def‘, 12.3]] >>> copy2 [‘change‘, [‘def‘, 12.3]]
深拷贝的id指向了同样的量
>>> [id(x) for x in origin, copy1, copy2] [47106648, 47106648, 47106648]
深浅拷贝还可以通过copy模块里的函数实现,copy.copy()是浅拷贝,copy.deepcopy()是深拷贝。