当前位置:   article > 正文

python中,tuple里的list中的元素为什么可以变,tuple到底可不可变?_tuple(list)会怎么样

tuple(list)会怎么样

众所周知,tuple与list的区别就是tuple是不可变的,是为了让程序更安全,tuple可以当作dict的key但是list不行。但tuple并不是完全不可变的,如下所示,tuple中的list的元素就是可以修改的。

  1. >>> a = 1
  2. >>> b = 2
  3. >>> c = [3,4,5]
  4. >>> d = (a,b,c)
  5. >>> d
  6. (1, 2, [3, 4, 5])
  7. >>> d[2][0]=9
  8. >>> d
  9. (1, 2, [9, 4, 5])

首先我们需要了解python中list的一些特性:

  1. >>> c
  2. [9, 4, 5]
  3. >>> c2 = c # 使用=定义一个新的list,实际上c2只是c的一个引用,修改c2中的元素,c也会同时被修改
  4. >>> c2
  5. [9, 4, 5]
  6. >>> c2[0]= 99
  7. >>> c
  8. [99, 4, 5]
  9. >>> id(c)
  10. 1868306709960
  11. >>> id(c2) # 发现c2和c的id是一样的,即二者的地址相同
  12. 1868306709960
  13. >>> c3 = [99, 4, 5] # 定义一个新的c3,元素组成与c2一样,不过此时虽然二者内容相等,但却是不同的list对象,占用的内存地址不同
  14. >>> c3 == c2 # == 只判断值是否相等
  15. True
  16. >>> c3 is c2 # is判断内存地址是否相同
  17. False
  18. >>> id(c3) # 发现c3的id与c2不同
  19. 1868306685576
  20. >>> id(c3[0]) # 查看c3里第一个元素的id
  21. 1885009424
  22. >>> c3[0]=999
  23. >>> id(c3[0]) # 修改c3[0]的值后,其id也随之改变,但是c3的地址不会发生改变
  24. 1868273844016
  25. >>> id(c3)
  26. 1868306685576

看完以上的代码,我们基本就能明白tuple中list中元素可变的原因:虽然list中的元素变了,但是list对象本身的内存地址并没有变,所以对tuple来说并没有元素发生变化。那么能否将list整体替换呢?理论上是不可行的,因为替换list本身会修改对象内存地址。看以下演示

  1. >>> d
  2. (1, 2, [99, 4, 5])
  3. >>> d[2] = 3 # 不可将list整体替换
  4. Traceback (most recent call last):
  5. File "<stdin>", line 1, in <module>
  6. TypeError: 'tuple' object does not support item assignment
  7. >>> d[2]=c2 # 即使是将list整体替换成内存地址相同的对象也不可以,python直接不允许这种操作,以避免错误操作
  8. Traceback (most recent call last):
  9. File "<stdin>", line 1, in <module>
  10. TypeError: 'tuple' object does not support item assignment

c++里的参数传递允许传递引用和指针(所以C++难呀),而在python里,参数的传递是传递对象引用

在python中,不可改变的对象有:str,int,float,tuple;可以改变的对象有list,dict,set。可变和不可变实际上指的是对象所占用的内存地址是否可变。下面以str和list演示可变和不可变的区别。

  1. >>> x = 'abc'
  2. >>> type(x)
  3. <class 'str'>
  4. >>> y = ['a', 'b', 'c']
  5. >>> type(y)
  6. <class 'list'>
  7. >>> x2 = 'abc' # 定义一个新的x2
  8. >>> y2 = ['a', 'b', 'c']
  9. >>> id(x), id(x2) # 比较两个内容相同的str的id,发现他们所占用的内存地址相同,
  10. (1868273892576, 1868273892576)
  11. >>> id(y), id(y2) # 比较两个内容相同的list的id,发现不同
  12. (1868306709832, 1868306709768)
  13. >>> x3 = x # 将x值赋给x3,此时二者占用的是同一个内存地址,相当于引用
  14. >>> x3
  15. 'abc'
  16. >>> x3 += 'd' # 修改x3时,由于x是str类型不可变,所以x并不会跟着变,x3此时实际上是调用了新的内存地址
  17. >>> x3
  18. 'abcd'
  19. >>> x
  20. 'abc'
  21. >>> y3 = y # 对于list正相反
  22. >>> y3
  23. ['a', 'b', 'c']
  24. >>> y3.append('d')
  25. >>> y3
  26. ['a', 'b', 'c', 'd']
  27. >>> y
  28. ['a', 'b', 'c', 'd']
  29. >>> y2
  30. ['a', 'b', 'c']

 int和float类型和str一样,dict和list一样,不过tuple虽然是不可变的,但和str不完全一样:

  1. >>> n = (1,2,3)
  2. >>> m = (1,2,3)
  3. >>> id(n), id(m) # 虽然tuple是不可变的,但是内容相同的两个tuple地址是不一样的,这和list类似。
  4. (1868306704208, 1868306704424)

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/305716
推荐阅读
相关标签
  

闽ICP备14008679号