首頁  >  問答  >  主體

能否用C++的指针/引用来类比解释一下Python中Tuple的“指向不变性”?

初学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赋值,却有两种不同的意义”的矛盾。有什么解释方式能调和这种矛盾么?】

表述的不太清楚,希望能有理解了我的疑问的朋友呀。多谢了。

怪我咯怪我咯2712 天前444

全部回覆(6)我來回復

  • PHP中文网

    PHP中文网2017-04-17 16:34:10

    你的類比是錯的。 myTuple=(myInt,myList)在任何時候都是:myTuple=(myInt,myList)在任何时候都是:

    &myTuple[0]=myInt;
    &myTuple[1]=myList;

    因为在Python里一切都是对象,myInt也是。tupleimmutable的意思是你无法为其元素重新赋值。也就是你不能改变myTuple[0]myTuple[1]这两个指针变量的值,所以它们永远指向myIntmyList,这一点是确定的。

    但是你可以修改tuple中的每个元素所指向的对象本身,前提是这个对象必须是可变的。比如你能够修改myList,因为这是一个可变对象。但是myInt rrreee

    因為在Python裡一切都是對象,myInt也是。 tupleimmutable的意思是你無法為其元素重新賦值。也就是你不能改變myTuple[0]myTuple[1]這兩個指標變數的值,所以它們永遠指向myInt和< code>myList,這一點是確定的。 🎜 🎜但是你可以修改tuple中的每個元素所指向的物件本身,前提是這個物件必須是可變的。例如你能夠修改myList,因為這是一個可變物件。但是myInt不行,因為整數也是不可變對象,所以你無法修改它。 🎜

    回覆
    0
  • 怪我咯

    怪我咯2017-04-17 16:34:10

    你把指針理解成一張上面寫有數字的小紙條,紙條上面的數字告訴你該去對應哪一個編號的抽屜裡面拿東西。

    那麼 Tuple 是這樣的:

    1. 當你有一個 myTuple 的時候,你有一張名字叫 myTuple 的紙條,根據數字你可以找到一個抽屜,抽屜裡面有一張或者多張另外的小紙條。而這些紙條的數量是確定的,直到你把 myTuple 這張紙條扔掉了(或者說 myTuple 上的數字換了另外一個),才有可能會變化。

    2. myTuple 從(myInt,)变成 (myInt, myList)的過程,實際上是myTuple 上面的數字改寫了,並且向新的數字對應的另外一個抽屜,放進去兩張紙條:第一張是原先的 myInt 紙條,第二張是新加進去的myList 紙條。

    3. 你對myList 添加或刪除任意元素,其實都是根據myList 紙條去找對應的抽屜去做事,跟myTuple 沒有多大關係,只不過是myTuple 裡面恰好有一張紙條的數字,跟myTuple 紙條的數字是一樣的。

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-17 16:34:10

    就是常指針唄。

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-17 16:34:10

    覺得可以用函數傳遞參數的情景解釋,
    1.可變對象傳引用:可以在原對像上改變,函數內外都持有對該對象的指針,函數內外使用的是一個對象,如果在函數內部改變該對象,函數外部也會改變,類似於引用傳遞。
    2.不可變物件傳拷貝:不可變物件不能在原來的記憶體空間上變化,所以如果要改變其值,解釋器會新建一個物件存放新的變量,這個時候函數內外使用的就不是一個物件了--函數外部還是用的以前的對象,而函數內部已經使用了一個全新的對象。

    回覆
    0
  • 天蓬老师

    天蓬老师2017-04-17 16:34:10

    myInt = 5
    myList = [3]
    print id(myList)  #id: 37216584
    myTuple = (myInt, myList)
    print myTuple  #(5, [3])
    myList.append(4)
    print id(myList) #id: 37216584
    print myTuple #(5, [3, 4])
    myList = [4, 5]
    print id(myList)# id: 37258584
    print myTuple #(5, [3, 4])

    先確定myList是list對象,指向一個地址(或引用,個人覺得像是指針),myTuple存有這個引用。因為是myList可變的,所以可以新增刪除,但它的地址都沒變,看先後兩次的id。如果將myList指向另一個對象,則地址改變了。這時改變的myList不會影響myTuple了。因為Tuple保存的那個list物件沒有變化,所以與myTuple無關。

    回覆
    0
  • 巴扎黑

    巴扎黑2017-04-17 16:34:10

    在python中,你這裡的myInt也是引用,指向某個整數實體,這跟c/c++不一樣,在c/c++中myInt就是整數實體本身了;這樣一來,Tuple裡存的都是引用,區別只是Int是不可變的,而List是可變的;
    所以你說的矛盾並不存在。

    回覆
    0
  • 取消回覆