2013年4月8日 星期一

python runtime 產生物件與 compile-time 產生物件方法的比較

    python 是一個很有彈性的語言,可是彈性也意味著,完成一件事情會有很多方法。這篇文章介紹產生產生 dict 與 type object 的方法。注意,以下討論都是未最佳化的情形。

    首先介紹產生 dict 的方法。在 python 中,產生 dict ( list 和 tuple 相同) 方法至少有兩種,一種是使用 {}, 另外一種是使用 dict() 的形式。前者是 compile-time 就會決定要產生 dict 物件,而後者是函數呼叫型式,他必須等到 run-time 時期才知道是產生 dic。至於後者較前者有何好處我就不清楚了。



    另外一個就是產生 type 的方法。在 python 中,可以使用 class 關鍵字來產生物件。例如

class Test(object):
    pass

    上面的語法,將產生一個名字叫 Test 的 type 物件。上面這個方法,在 compile-time 時期就會決定要產生 Test 這個 type 物件了。另外一個產生 type 的方法是使用 type 函數。

Test1 = type('Test1', (object,), {})

     上面的方法會產生一個名字叫 Test1 的方法。毫無疑問,他是在 run-time 時期產生物件。前者較後者減少了一個 function call。但是後者有個優點,因為它是 run-time 時期產生物件的,所以可以在 run-time 時期決定該型別的模樣,而不是一開始就寫死了。

    在介紹我想到的最後一種,要做到過濾的方法,你可以使用 filter 函數,你也可以考慮使用 list comprehensions。

a = [1, 2, 3]
a = filter(lambda s: s > 1, a)
b = [1, 2, 3]
b = [ s  for s in b if s > 1]

    前者呼叫函數來做過濾物件,所以是 run-time 時期決定過濾物件。後者則是 compile-time 時,就知道那個敘述可能要做過濾物件。為什麼我說可能,因為 list comprehensions 不只可以做到 filter 的功能, 還可以做到 map 的功能。不過執行實際的過濾動作時,還是在 run-time。沒辦法,資料只有 run-time 時才知道。



註1: python 類別有新式類別和舊式類別之分。用新式類別(有繼承 object) 的寫法產生的物件是 type 物件。然而使用舊式類別 的寫法產生的物件是 classobj

註2:  我們都知道,python 中任何東西都是物件。所以function (用 def 產生的,當然用 def 也可以用來產生 method)也是個物件,只是它可以被呼叫( 有定義 __call__)。然而, type 物件(用 class 產生的) 也是個物件, type 物件也有定義 __call__ 方法,用來產生 instance 物件。

註3:  如果你想要讓你的 instance 可以被呼叫,只要在它的 type 物件定義 __call__ 即可。如以下程式碼。

class CallableType(object):
    def __call__(self):
        print 'I can be called, also'

ins1 = CallableType()
ins1()

沒有留言:

張貼留言