2012年5月17日 星期四

[Python]Python和C之間的差異 - Python的型別和物件

這篇文章主要是想幫助那些從C轉換跑道到Python來的程式設計師
首先先解釋一個差異很大的地方,Python的型別(types)和物件(objects)

在Python中所有的東西都是object

string是object,int是object,function是object,連code都是object
這點和C或是C++非常的不同
我們可以用一個內建的function type()來得知一個object的type
>>> s = "sway"           #"sway"是一個string的object
>>> type(s)        
<type 'str'>
>>> i = 2                #2是一個int的object
>>> type(i)
<type 'int'> 
>>> def hello(): pass    #hello()是一個function的object  
...
>>> type(hello)
<type 'function'>
>>> type(hello.__code__) #hello()的code是存在一個code的object 
<type 'code'>

Python是動態型別(Dynamic Typing)的程式語言,和C和C++這類的編譯語言不一樣
C和C++變數的型別都在編譯時候就決定好了
而Python則是在執行期(Run Time)才決定type
>>> s = "sway"    #這時候s的type是string
>>> type(s)

>>> s = 2         #這時候s的type變成int了
>>> type(s)








由上面範例可以帶出一個Python很重要的觀念
Python variable的type完全被它所對應到的object所決定的
這在Python中稱為reference
每一個variable其實就像是C裡頭的pointer
先建立object之後,才用variable指向新建立的object,相當於給object一個別名
因此Python的variable其實就是reference

當我們執行i = 2的時候,其實Python會先建立一個integer的object叫做2
之後再產生一個variable並且把它指向2這個integer的object
Python的variable其實就只是一個name而已,我們透過這個name去間接access到object
這點是Python和C、C++很不一樣的地方,這也是大多數C programmer剛轉過來不太適應的地方
由於Python的這種特性,很多神奇的事情就發生了
>>> a = [1, 2, 3]
>>> b = a
>>> b[0] = 4
>>> print a
[4, 2, 3]
很多人看到這邊可能會覺得很奇怪,明明是修改b的值怎麼連a的值也被改到了?













其實原因很簡單,因為b = a這行程式碼其實只是把b指到a所指向的object而已
因此當執行完這行程式碼後,a和b就都指向同一個object
不論是改a或是改b,最後都會對應到同一個object
這是Python初學者最容易詢問的問題之一,其實只要搞懂Python的object架構,一切就會變得很直覺

上面範例如果object是一個不可改變(immutable)的object,情況就有點不一樣了。不可改變(immutable)的object像是:string, integer......
因為object是不可改變的,當你嘗試去更改object的時候,會自動建立新的物件,而不會更動到所指向的object。
聽起來有點難懂,看以下範例就知道了
>>> a = 2
>>> b = a
>>> id(a)                #id(a)可以取得a指向物件的id
17500064
>>> id(b)
17500064                 #a 和 b指向同一個物件(integer 2)
>>> b = 4
>>> print a
2
>>> id(b)                #b指向一個新的物件(integer 4)
17500016
由以上範例可以知道,兩個reference指向同一個不可改變的object時。因為object不可改變的特性,透過其中一個reference試圖去修改object都會自動建立一個新的物件

相反地,兩個reference指向同一個可改變(mutable)的object時。因為我們可以直接修改object的關係,所以透過其中一個reference去修改object不會建立新的物件。會直接修改到指向的object,因此透過任何一個reference去取值看起來就好像兩邊都被改過一樣。

All "variables" are references. 這是Python和C很不一樣的地方。

4 則留言:

  1. 那我要是真的要創造一個immutable物件的refernce呢,該怎麼辦?
    例如:
    a = 1
    b = a
    a = 2
    >> b
    >> 1 #我想讓它也變成2

    回覆刪除
    回覆
    1. 似乎是沒有辦法

      刪除
    2. >>> a = [1]
      >>> b = a
      >>> a[0] = 2
      >>> b[0]
      2

      刪除
  2. 感謝大大的解析,很受用

    回覆刪除