2009-12-16 23 views
1

對於Python我還是比較新的,我正在嘗試使用它的動態類型。有時候我有一個函數或者一個類,它需要一個特定類型的參數,但是可以得到另一個強制的類型的值。例如,它可能會得到一個float,而是接收一個int或一個小數。或者它可能期望一個字符串,但是會接收一個定義了特殊方法的對象。在Python中強制/轉換爲正確類型的最佳位置

將參數強制轉換爲正確類型(及其原因)的最佳做法是什麼?我是否在函數/類或調用者中執行?如果在調用者中,我是否也在函數中檢查它?例如。

選擇1:

def myfunc(takes_float): 
    myval = float(takes_float) 

myfunc(5) 

備選方案2:

def myfunc(takes_float): 
    myval = takes_float 

myfunc(float(5)) 

方案3:

def myfunc(takes_float): 
    assert isinstance(takes_float, float) 
    myval = takes_float 

myfunc(float(5)) 

我已經閱讀this answerthis one,他們說在Python中檢查類型是「不好」的,但我不想浪費時間來追蹤編譯器以靜態類型語言即時拾取的非常簡單的錯誤。

+0

不要使用'assert'那樣的。斷言意味着記錄在運行時不可能發生的條件,而不是用於驗證輸入。 – 2009-12-16 18:18:25

+0

是的,除非有錯誤,否則不可能發生。在替代方案3中,調用者必須將值轉換,這將是一個錯誤。 – EMP 2009-12-16 21:48:51

回答

8

當你不這樣做,而且不是更早的時候,你「強迫」(也許 - 它可能是一個noop)。例如,假設你有一個函數,它接受一個float並返回其正弦和餘弦的總和:

import math 
def spc(x): 
    math.sin(x) + math.cos(x) 

應該在哪裏你「要挾」 X浮動?答:無處可言 - 正弦和餘弦做的工作適合你,例如:

>>> spc(decimal.Decimal('1.9')) 
0.62301052082391117 

所以當它是不可缺少的強制(儘可能晚)?例如,如果你想在一個參數上調用字符串方法,你必須確保它是一個字符串 - 試圖調用例如.lower無字符串將不起作用,len可能會工作,但如果arg是例如,則執行與預期不同的操作。一個列表(給你列表中的項目數量,而不是它表示爲字符串的字符數量),等等。

至於捕捉錯誤 - 認爲unit tests - 半自動單元測試將捕獲所有錯誤靜態類型會,然後一些。但是,這是一個不同的主題。

+0

s /陳述/靜態/ – 2009-12-17 01:10:35

+0

@Andrey,是的,聽起來更好 - 讓我修復A,謝謝。 – 2009-12-17 03:09:42

2

這真的取決於。爲什麼你需要 a floatint會打破這個功能嗎?如果是這樣,爲什麼?

如果您需要的參數,以支持功能/特性,一個float具有而是int不應該檢查該功能/性能,該參數恰好是一個float。檢查對象是否可以做你需要它做的事情,而不是它碰巧是你熟悉的特定類型。

誰知道,也許有人會發現Python的實現float的一些主要問題,並創建一個notbrokenfloat庫。它可能支持浮動功能在修復某些異常bug時的所有功能,但其對象不屬於float類型。手動將它鑄造到float可能會消除這個漂亮的新課程的所有好處(或可能會徹底破壞)。

是的,這是一個不太可能的例子,但我認爲這是在使用動態類型語言時正確的思維方式。

0

恰好有一次整數與浮點數成爲問題。這是唯一一次你會發現一個奇怪的「簡單」錯誤和調試挑戰。

司。

當你需要它時,其他的一切都會進行你需要的轉換。

如果您正在使用Python 2.x並且隨意丟棄/運算符而沒有想到,那麼您可以 - 在某些常見情況下 - 做錯了事情。

你有幾種選擇。

  1. from __future__ import division會給你Python 3的語義分割。

  2. 隨時用-Qnew選項運行以獲得新的除法語義。

  3. 使用float接近/操作。

分區是類型可以唯一重要的地方。這是唯一一次整數行爲與浮點數不同的方式,會悄悄地影響你的結果。

所有其他類型的不匹配問題都將以TypeError例外而失敗。所有其他人。你不會浪費時間調試。你會立即知道什麼是錯的。


更具體一點。

沒有調試「期望一個字符串,但沒有得到一個字符串」。這會立即崩潰並追溯。沒有混淆。沒時間想念。如果一個函數需要一個字符串,那麼調用者必須提供字符串 - 這就是規則。

上面的替代2用於RARELY來糾正問題,你有一個函數,期望一個字符串,你有困惑,忘了提供一個字符串。這個錯誤發生在RARELY上,它導致了一個直接的類型異常。

+0

謝謝,很高興知道這個選項 - 但整數/浮點數只是一個例子。還有其他的問題。 – EMP 2009-12-16 22:03:17

+0

@Evgeny:真的嗎?你可以提供任何?唯一令人困惑的是int/float。 AFAIK,除了明顯的例外,所有其他人死亡。請提供一個不會因例外而死亡的操作示例。 – 2009-12-16 23:56:48

+0

另一個例子是在我原來的文章中:該方法可能期望一個字符串,但接收一個定義'__str__'特殊方法的對象。在某處我需要調用'str()',但是在哪裏? – EMP 2009-12-17 00:02:14

相關問題