初学Python,有一定C/C++基础。
看到Tuple的"immutable"的时候产生了这样一个疑问。
根据我的理解,如果Tuple的元素是普通变量(e.g. myInt=5),那创建
myTuple=(myInt,)
的意义就是
myTuple=(myInt的值,)
因此是不变的。
但是如果myTuple=(myInt,myList),虽然myTuple[1]永远都指向myList,但是myList中的内容是可以改变的。看到有人表示这Tuple里的List实际上是myList的引用。那能否用C++的指针/引用来类比统一解释一下这种Tuple元素的immutable特性呢?
【补充一下:比如对于myTuple=(myInt,myList),定义的时候,从意义上感觉(非严谨),就像是用C++写:
myTuple[0]=myInt; //myInt之后发生了什么都和myTuple[0]无关了,myTuple[0]只决定于myInt当前值
&myTuple[1]=myList; //而myTuple[1]更像是myList的一个引用。myList如果变化,myTuple[1]也会变化
于是这里就产生了“同样是对Tuple赋值,却有两种不同的意义”的矛盾。有什么解释方式能调和这种矛盾么?】
表述的不太清楚,希望能有理解了我的疑问的朋友呀。多谢了。
你的類比是錯的。
myTuple=(myInt,myList)
在任何時候都是:myTuple=(myInt,myList)
在任何时候都是:因为在Python里一切都是对象,
myInt
也是。tuple
是immutable
的意思是你无法为其元素重新赋值。也就是你不能改变myTuple[0]
和myTuple[1]
这两个指针变量的值,所以它们永远指向myInt
和myList
,这一点是确定的。但是你可以修改
因為在Python裡一切都是對象,tuple
中的每个元素所指向的对象本身,前提是这个对象必须是可变的。比如你能够修改myList
,因为这是一个可变对象。但是myInt
rrreeemyInt
也是。tuple
是immutable
的意思是你無法為其元素重新賦值。也就是你不能改變myTuple[0]
和myTuple[1]
這兩個指標變數的值,所以它們永遠指向myInt
和myList,這一點是確定的。 🎜 🎜但是你可以修改tuple
中的每個元素所指向的物件本身,前提是這個物件必須是可變的。例如你能夠修改myList
,因為這是一個可變物件。但是myInt
不行,因為整數也是不可變對象,所以你無法修改它。 🎜你把指針理解成一張上面寫有數字的小紙條,紙條上面的數字告訴你該去對應哪一個編號的抽屜裡面拿東西。
那麼 Tuple 是這樣的:
當你有一個 myTuple 的時候,你有一張名字叫 myTuple 的紙條,根據數字你可以找到一個抽屜,抽屜裡面有一張或者多張另外的小紙條。而這些紙條的數量是確定的,直到你把 myTuple 這張紙條扔掉了(或者說 myTuple 上的數字換了另外一個),才有可能會變化。
myTuple 從
(myInt,)
变成(myInt, myList)
的過程,實際上是myTuple 上面的數字改寫了,並且向新的數字對應的另外一個抽屜,放進去兩張紙條:第一張是原先的 myInt 紙條,第二張是新加進去的myList 紙條。你對myList 添加或刪除任意元素,其實都是根據myList 紙條去找對應的抽屜去做事,跟myTuple 沒有多大關係,只不過是myTuple 裡面恰好有一張紙條的數字,跟myTuple 紙條的數字是一樣的。
就是常指針唄。
覺得可以用函數傳遞參數的情景解釋,
1.可變對象傳引用:可以在原對像上改變,函數內外都持有對該對象的指針,函數內外使用的是一個對象,如果在函數內部改變該對象,函數外部也會改變,類似於引用傳遞。
2.不可變物件傳拷貝:不可變物件不能在原來的記憶體空間上變化,所以如果要改變其值,解釋器會新建一個物件存放新的變量,這個時候函數內外使用的就不是一個物件了--函數外部還是用的以前的對象,而函數內部已經使用了一個全新的對象。
先確定myList是list對象,指向一個地址(或引用,個人覺得像是指針),myTuple存有這個引用。因為是myList可變的,所以可以新增刪除,但它的地址都沒變,看先後兩次的id。如果將myList指向另一個對象,則地址改變了。這時改變的myList不會影響myTuple了。因為Tuple保存的那個list物件沒有變化,所以與myTuple無關。
在python中,你這裡的myInt也是引用,指向某個整數實體,這跟c/c++不一樣,在c/c++中myInt就是整數實體本身了;這樣一來,Tuple裡存的都是引用,區別只是Int是不可變的,而List是可變的;
所以你說的矛盾並不存在。