2010-03-26 49 views
19

在類中進行錯誤檢查的正確方法是什麼?提出例外?設置包含所有錯誤並返回它的實例變量字典「錯誤」?在設置變量時引發錯誤的Python中的正確方法

從班上打印錯誤不好嗎? 如果我發起異常,我必須返回False嗎?

只是想確保我做正確的事情。以下是一些示例代碼:

@property 
def password(self): 
    return self._password 

@password.setter 
def password(self,password): 
    # Check that password has been completed 
    try: 
     # Check that password has a length of 6 characters 
     if (len(password) < 6): 
      raise NameError('Your password must be greater \ 
          than 6 characters') 

    except NameError: 
     print 'Please choose a password' 
     return False 

    except TypeError: 
     print 'Please choose a password' 
     return False                                 

    #Set the password 
    self._password = password 

    #Encrypt the password 
    password_md5 = md5.new() 
    password_md5.update(password) 
    self._password_md5 = password_md5.hexdigest() 
+1

該代碼中名爲'password'的東西太多了。 (第一個函數,第二個函數和第二個函數的參數).pyflakes將成爲你的朋友。 – keturn 2010-03-26 20:51:21

+0

@keturn:它是'property()'函數文檔中顯示的模式。看看[使用'.setter'裝飾器]的文檔中的代碼示例(https://docs.python.org/3/library/functions.html#property)。在setter方法中'password'是一個局部變量(參數)。其他名稱位於不同的名稱空間中(它們屬於該類)。 – jfs 2017-07-05 15:51:13

回答

28

您的代碼不在上下文中,所以不是明顯的正確選擇。下面的一些技巧:

  • 不要使用NameError例外,當一個名字,作爲例外本身說,沒有在本地或全球範圍內發現它只是用來使用ValueErrorTypeError如果異常關注參數的值或類型;

  • 不要打印錯誤消息。提高有意義的異常與有意義的錯誤消息:

    raise ValueError("password must be longer than 6 characters") 
    
  • 返回從二傳手的值是沒有意義的,而賦值不是一個表達式,即你可以不檢查一個分配的值:

    if (user.password = 'short'): ... 
    
  • 只需在setter中引發異常,並讓設置屬性的代碼處理它。

實施例:

class Test: 

    minlen = 6 

    @property 
    def password(self): 
     return self._password 

    @password.setter 
    def password(self, value): 
     if not isinstance(value, basestring): 
      raise TypeError("password must be a string") 
     if len(value) < self.minlen: 
      raise ValueError("password must be at least %d character len" % \ 
           self.minlen) 
     self._password = value 

看也是在this forms handling library,存在的驗證,here an example,是在他們自己的實體:它們可以動態地與更高控制和較少耦合的代碼被設定,但也許這是遠遠超過您的需要。

+1

這真的很有幫助。謝謝。 – ensnare 2010-03-26 20:14:31

+0

@mg,整體而言,好帖子(和偉大的縮寫!),但我最後關心的例子。你似乎已經組成了一個'密碼'裝飾器,其用法很奇怪;你的意思是'@ property'並命名第一個方法'password'?另外,如果要使用屬性,則必須使用新樣式類,即將示例的第一行更改爲'class Test(object):'或從其他一些新樣式類繼承。 (即使你還沒有使用屬性,你應該使用新式的課程。) – 2010-03-26 22:35:48

+0

@Mike Graham:該死,疲倦可能會帶來不好的笑話。你對物業命名是正確的,確切的形式是最初由ensare使用的形式,我更喜歡舊的好的'password = property(...)',但是我會與ensare一致而不真正瞭解新的2.6語法。第二種觀察是不正確的:屬性可以與舊式類一起使用 – 2010-03-27 01:16:45

10

在python中發出錯誤信號的標準方式是引發異常並讓調用代碼處理它。或者讓NameError & TypeError繼續向上,或者捕獲它們並引發您定義的InvalidPassword異常。

雖然可以像您那樣從函數返回成功/失敗標誌或錯誤代碼,但不建議這樣做 - 調用方忘記檢查返回值並使錯誤丟失很容易。除了你從屬性設置器返回一個值 - 這在Python中是沒有意義的,因爲賦值不是表達式,並且不能返回值。

你也不應該在你的異常處理中爲用戶打印消息 - 如果你以後想要在GUI程序中使用函數或類會怎麼樣?在這種情況下,您的打印語句將無處可打印。將錯誤記錄到日誌文件(使用Python的日誌記錄模塊)通常對調試很有幫助。

4

通常,您應該指出使用異常傳播的錯誤。如果您通過剛剛檢查過的內容發現錯誤,並且可以立即處理,則不需要引發異常。

在例如setter的特定情況下,返回False或其他任何內容都無濟於事。設置你必須檢查的實例變量是非常不理想的,因爲那樣你可能會錯過意外的錯誤。

print通常不會很好地迴應錯誤。在這種情況下,聽起來好像你想告訴最終用戶他們需要使用不同的密碼。這聽起來像你應該調用一個方法,導致帶有表單的網頁向用戶解釋出了什麼問題;你可以調用那些在你的類中實現的方法,或者拋出一個會傳播並最終被捕獲並用於這個目的的異常。 (這是一般性建議,我不太瞭解主塔告訴你它是如何要你這樣做的。)

你不應該提出自己的NameError例外。 NameError很多東西總是表示在你的程序中出現了一個錯字,因此你通常不想去捕捉它。通過捕捉它,你會在程序中引入不必要的不​​確定性。這看起來可能更像ValueError或其子類(class InvalidPasswordError(ValueError): pass)。

我不明白你爲什麼要檢查TypeError。你應該永遠明白什麼會導致你發現的異常。如果你在這種情況下,這很好,我無法弄清楚什麼樣的錯誤會引起TypeError,你可以通過提示用戶明確地處理。

您以純文本格式接收密碼並存儲其md5散列的技術並不十分安全。你應該看看像AuthKit這樣可以使這個過程更安全和抽象的東西。

相關問題