我構建了這兩個代碼,我想知道哪個更好。由於這不是我的程序所關心的,所以我並不一定意味着哪一個更快執行。哪一個更具可讀性?Python:哪個代碼更好?
或者:
A = 1
B = some_other_value
try:
A /= B
except ZeroDivisionError:
pass
或者:
A = 1
B = some_other_value
if B != 0:
A /= B
我構建了這兩個代碼,我想知道哪個更好。由於這不是我的程序所關心的,所以我並不一定意味着哪一個更快執行。哪一個更具可讀性?Python:哪個代碼更好?
或者:
A = 1
B = some_other_value
try:
A /= B
except ZeroDivisionError:
pass
或者:
A = 1
B = some_other_value
if B != 0:
A /= B
當然第二個:
A = 1
B = some_other_value
if B != 0:
A /= B
不是因爲它更具可讀性,但因爲你沒有使用一個例外非特殊情況。如果無效輸入或在正常情況下可能導致錯誤的輸入是可能的,那麼您絕不應該使用異常來處理它。
你可以找到(旁邊性能)關於這個網絡上,但在我看來很不錯的解釋總是因爲意圖的:當你處理異常,那麼你明確地告訴讀者,這是一個異常情況,一個錯誤,這在正常的程序流程中不應該發生。在你的情況這不是因爲一個無效的輸入是絕對可能的(每個輸入必須被驗證,總是)。
從我的角度來看,你想要處理它的事實意味着這是可能的,然後檢查總是正確的解決方案。就像Ryan所說的,如果你不需要檢查零值,你可能會有更高的多態性,那麼你需要做的是移動支票來處理這種情況(例如在/運算符中,而不是在你使用它的地方)。
編輯
很少有詞彙可以總結我寫的評論。 Python鼓勵一種名爲EAFP的編程風格,當你編寫小腳本時,這是一個很好的資源,但在編寫應用程序和庫時應該謹慎使用它。
它有助於保持碼短(和快速爲最常見的代碼路徑),但它有一個大缺點:如果你不try
/execpt
包裝每個幾行你會必須處理中間結果和部分計算。一個大的try
可能會使應用程序處於不確定狀態(否則它會使您的代碼更不易讀,因爲長列表可能是嵌套的 - try
/except
/else
/finally
)。
我同意它有助於使用你的代碼的情況下,你甚至沒有去想但這不靈活,這是脆弱。對於簡短的個人腳本也許可以,但是如果我編寫一個應用程序(或者甚至更多的庫),我想確定我的代碼在哪裏以及如何失敗,我會編寫測試以檢查它如何與不同的輸入一起工作。我不希望它會以我無法預知的方式失敗,意外的輸入>意外的行爲聽起來太像垃圾輸入>垃圾輸出。應用程序必須健壯。在你檢查完你可以檢查的所有東西之後,你甚至必須爲異常情況做好準備(我可以放鬆這個規則,以便檢查可能是偏執的)。
除以零並不例外? –
@HunterMcMillen **不,它不是**,因爲輸入必須總是**驗證**,特別是如果你認爲它可能發生(除了塊以外的空白讓我認爲他們必須是)。 –
@Adriano EAFP更加pythonic,輸入驗證通常是不鼓勵的。而且你需要在此之上進行類型測試來實際驗證輸入,這很少被鼓勵。 –
第二個可能更具可讀性,但第一個允許更大的多態性和鴨子打字(在B不是float
或int
,但是支持除法的對象)的情況下。
大多數討論在這裏似乎是缺少點是B
可能是支持部門自定義對象。請考慮下面的例子,其中NumType
作爲分母。
>>> class NumType(object): # basically, an int wrapper
... """Custom number type. Supports division when it is the denominator"""
... def __init__(self, val):
... self.val = val
... def __rdiv__(self, num):
... return num/self.val
...
>>> c = NumType(1) #normal division works as expected
>>> 5/c
5
>>> c = NumType(7)
>>> 5./c
0.7142857142857143
>>> c = NumType(0)
>>> 5/c # 0 division causes exception
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __rdiv__
ZeroDivisionError: integer division or modulo by zero
>>> # pay attention here:
>>> if c != 0: # condition is True because c is an object, not 0
... print 5/c # so this division still occurs, and generates an exception
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 5, in __rdiv__
ZeroDivisionError: integer division or modulo by zero
>>> # however, this is caught with a try/except
>>> try:
... 5/c
... except ZeroDivisionError:
... print '0 division'
...
0 division
答案是:取決於。
您是否可以輕鬆編寫適當的測試來處理條件。在這種情況下,你可以。
另一個考慮因素是你的手寫測試是否足夠。在一行代碼中,這很容易。如果你有很多操作,假設一切都很好,並且事後弄清楚,例外情況可能更有意義。 (當然,在這種情況下,輸入驗證通常會更有用)。
與編程中的大多數事情一樣,這是風格和品味的問題。在python中尤其如此,python通常具有多種處理方式(儘管你可能已經閱讀過任何復活節彩蛋),而且它主要基於程序員能夠做出自己的決定的想法(不像Java,確實試圖強制執行一種編程風格,通過使所有事情都比預期的技術更難以且更令人不快)。
想想你在做什麼,爲什麼。儘量不要重複自己。
**既不是**,因爲這兩個代碼位有效地隱藏了計算出現問題的事實。 –
重複的:http://stackoverflow.com/questions/1835756/using-try-vs-if-in-python – Wessie
python使用異常流控制的事實並不意味着你應該只使用異常流控制。 – mishik