2017-04-05 28 views
1

我意識到已經討論過是否使用If/Else或Try/Except塊。這樣的問題所在位置:Better to 'try' something and catch the exception or test if its possible first to avoid an exception?嵌套Try/Except或If/Else - 如何判斷使用哪一個?

但我想討論一點點進一步擴大到嵌套try/except嵌套if/elif/else邏輯塊。這是設置...我想寫一個函數,允許用戶提供字符串文字,整數或迭代。這是一個高級函數,它將爲我寫的其他函數提供一定程度的抽象。我的代碼是像這樣:

def high_level_func(parameter = None): 
    """ 
    :param parameter: Can accept the string 'All', a single integer, or an iterable such 
     as a range or a list or tuple of ints. 
    """ 
    try: 
     if parameter.lower() == 'all' 
     # .lower because str input should be case-insensitive 
      return str_all_function(parameter) # Only accepts the 
        # string 'all' - case insensitive 
    except AttributeError: 
     # if parameter is an int or iter end up here because those types 
     # don't have .lower() methods 
     try: 
      for para in parameter: 
       try: 
        print(int_input_function(parameter)) 
       except MyException: 
        raise MyException('An iter of something other than ints was ' 
             'provided and cause this error.') 
     except TypeError: 
      # parameter must be an int because ints aren't iterable and end up here 
      return int_input_function(parameter) 

在這種情況下,讓我們假設我不知道是什麼類型的輸入的大多數用戶都會喜歡(即它同樣可能是任何給定的用戶將通過其中一個int,一個iter,或字符串'all'。但是我們可以安全地假設用戶很可能永遠不會傳遞字符串或字符串列表-illegal iter s)

這是好的做還是我會更好地檢查輸入類型並執行if/elif/else(IEE)代碼塊?在您看來,IEE代碼塊是否會更容易閱讀?

備選建議:使用try/except和IEE的組合怎麼樣?例如,try/except可能嘗試降低輸入,如果它是字符串文字'all',並且IEE將嵌套在except塊中以檢查備選情況(整數或iter或非法類型)

在更一般的情況下,如何在三個不同的時間寫入函數並測試每一個函數來判斷哪個方法最快?

更進一步的問題是,如果Try/Except平均比If/Elif/Else測試更快,但我們認爲If/Elif/Else具有更好的可讀性,Try/Except方法應該快多少爲了保證將可讀性拋出窗外,或者在速度方面總是佔優勢?還是由編碼員/團隊決定?

+0

Python的建議EAFP模型(更容易請求原諒比許可),所以使用嘗試 - 除了pythonic路要走。就個人而言,我會去非pythonic路線,並使用if isinstance(參數,collections.Iterable)來劃分驗證,以避免級聯try-excepts。至於性能,我會建議您編寫一個更簡單的版本並使用testit模塊進行測試。 –

+0

有關更多信息,我確實運行了比較的簡化版本超過100,000次迭代,發現使用isInstance的If/Elif/Else比try/except方法更快。 (儘管我沒有使用testit模塊。)因此,在這種情況下,使用If/Else方法似乎是可讀性和雙贏的。只是不知道爲什麼。 嘗試/除法:超過100,000循環的1.34000015258789秒 如果/ Elif/Else方法:1.18899989128112超過100,000循環的秒數 – boymeetscode

回答

1

我認爲你的輸入函數應該負責驗證輸入,而不是調用它們的函數。在此之後,你可以讓高級的功能,保持較高的水平,並保持try ING使用其中的一個,直到成功:在這種情況下

def high_level_function(parameter=None): 
    try: 
    return str_input_function(parameter) 
    except ValueError: # Raised by str_input_function on bad input. 
    pass 

    try: 
    return iter_input_function(parameter) # MyException now propagates itself. 
    except ValueError: # Raised by iter_input_function on bad input. 
    pass 

    try: 
    return int_input_function(parameter) 
    except ValueError: # Raised by int_input_function on bad input. 
    pass 

    # This should never be hit: 
    raise ValueError("parameter has unsupported type: " + type(parameter).__name__) 
+0

感謝您的洞察。它簡單,乾淨,可讀,並且仍然遵循EAFP的python方法。過度思考這個問題對我自己很生氣。我傾向於用python來做到這一點。 GRRRR。 – boymeetscode

+0

沒問題! FWIW,我認爲你是在正確的軌道上。 –

+0

當我達到「返回」狀態時,我應該離開high_level_function,對吧?我正在測試我的代碼,看起來像我正在經歷所有的try塊,儘管每個try塊都有一個return語句,我期望它能成功,但事實並非如此。確保我所期望的和python的做法是一回事。 – boymeetscode

相關問題