python:一些关于元组的碎碎念
初始化元组的时候,尤其是元组里面只有一个元素的时候,会出现一些很蛋疼的情况:
def checkContentAndType(obj): print(obj) print(type(obj)) if __name__=="__main__": tuple1 = (1)#坑爹的初始化,这个写法初始化出来是个int!!! checkContentAndType(tuple1) tuple1 = (1,)# checkContentAndType(tuple1) list1 = [1] checkContentAndType(list1) set1 = {1} checkContentAndType(set1) dict1 = {1: 1} checkContentAndType(dict1)
运行结果是:
1 <class 'int'> (1,) <class 'tuple'> [1] <class 'list'> {1} <class 'set'> {1: 1} <class 'dict'> Process finished with exit code 0
第一个初始化出来的居然是个int!,真坑,所以元组里面至少要有一个逗号这个奇怪的经验就出现了
然而,初始化时候还有什么骚操作呢?看这个:
def checkContentAndType(obj): print(obj) print(type(obj)) if __name__=="__main__": tupleTest=1,2,3,'4',5 checkContentAndType(tupleTest)
他得到的居然还是一个元组!!!没有括号也可以成为元组啊!(嗯,不能自动成为list,也不能成为set,dict也不行,就是tuple)
(1, 2, 3, '4', 5) <class 'tuple'>
于是我们想,python解包原理可以给多个变量同时赋值,看看会发生什么?
def checkContentAndType(obj): print(obj) print(type(obj)) if __name__=="__main__": tupleTest1,tupleTest2=1,2,3,'4',5 Traceback (most recent call last): File "C:/Users/avatu/PycharmProjects/play/坑爹的初始化.py", line 6, in <module> tupleTest1,tupleTest2=1,2,3,'4',5 ValueError: too many values to unpack (expected 2) Process finished with exit code 1
emmmmm,果然,不能这样做,稍微修改一下:
def checkContentAndType(obj): print(obj) print(type(obj)) if __name__=="__main__": tupleTest1,tupleTest2=1,(2,3,'4',5) checkContentAndType(tupleTest1) checkContentAndType(tupleTest2) 1 <class 'int'> (2, 3, '4', 5) <class 'tuple'> Process finished with exit code 0
和之前的经验不冲突,第一个果然还是变成了个int,后面的成功分配给第二个标识符,成为了一个元组......
再改一改:
def checkContentAndType(obj): print(obj) print(type(obj)) if __name__=="__main__": tupleTest1,tupleTest2=(1,2,3),('4',5) checkContentAndType(tupleTest1) checkContentAndType(tupleTest2) (1, 2, 3) <class 'tuple'> ('4', 5) <class 'tuple'> Process finished with exit code 0
emmmmm,没被毛病,按照预计运行了.很好...!
关于很多书上都说,元组的元素不能修改。
我们来看一个诡异的例子:
def checkContentAndType(obj): print(obj) print(type(obj)) if __name__ == "__main__": tuple1 = ([1], 2, 'str-1', 'str-2') for i in range(len(tuple1)): if i == 0: tuple1[i].append('Pep8 is fun') print(tuple1[i])
结果:
[1, 'Pep8 is fun'] 2 str-1 str-2 Process finished with exit code 0
哎呦,我去,怎么改了????
然而,真的改了吗?...再看下面例子:
def checkContentAndType(obj): print(obj) print(type(obj)) if __name__ == "__main__": tuple1 = ([1], 2, 'str-1', 'str-2') for i in range(len(tuple1)): if i == 0: # tuple1[i].append('Pep8 is fun') tuple1[i]=[1,'Pep8 is fun'] print(tuple1[i])
结果:
Traceback (most recent call last): File "C:/Users/avatu/PycharmProjects/play/坑爹的初始化.py", line 11, in <module> tuple1[i]=[1,'Pep8 is fun'] TypeError: 'tuple' object does not support item assignment Process finished with exit code 1
嗯?怎么append()可以,赋值就不行了呢?
其实很简单.我们说python是完全面向对象的语言,那么一个int,一个list,都是一个对象,元组里面并不是把对象本身给塞进去了,而是把对象的指针给塞进去了!!!
看完下面这个例子就明了啦:
def checkIdAndValue(obj): print(id(obj)) print(obj) if __name__ == '__main__': list1 = [1, 2, 3] checkIdAndValue(list1) list1.append(4) checkIdAndValue(list1)
结果:
2603360595784 [1, 2, 3] 2603360595784 [1, 2, 3, 4] Process finished with exit code 0
你看,append()并没有改变原有list的id()...也就是说,地址没变啊!想想C语言....数据结构的首地址 bla bla bla......
再看等号:
def checkIdAndValue(obj): print(id(obj)) print(obj) if __name__ == '__main__': list1 = [1, 2, 3] checkIdAndValue(list1) list1.append(4) checkIdAndValue(list1) list1 = [1, 2, 3, 4] checkIdAndValue(list1)
结果:
2596211797832 [1, 2, 3] 2596211797832 [1, 2, 3, 4] 2596211888584 [1, 2, 3, 4] Process finished with exit code 0
对象的id发生变化了啊!
这样,就明白了,元组里面元素"可以被改变"的表象下,深层的原理:锁定的是一个指向对象的地址,但不是锁定了这个对象.
同样的原理:
def checkContentAndType(obj): print(obj) print(type(obj)) if __name__ == "__main__": tuple1 = ([1], {2, 3},{4:5, 6:7}, 'str-1', 'str-2') for i in range(len(tuple1)): if i == 0: tuple1[i].append('Pep8 is fun') elif i == 1: tuple1[i].add('Pep8 is fun') elif i == 2: tuple1[i][8] = 9 #K-V操作 print(tuple1[i])
结果:
[1, 'Pep8 is fun'] {2, 3, 'Pep8 is fun'} {4: 5, 6: 7, 8: 9} str-1 str-2 Process finished with exit code 0
凡是这种修改后不造成id()变化的操作,都能从表面上去改变一个元组.
你看,以前学的值引用和址引用的知识用上了吧? 哈哈