2013-12-19 121 views
3

我正在工作的一個小方項目,並已做出一些類和方法。其中一個類代表我們庫存中的一個貨架,另一個代表貨架上的每個貨架。我有一個方法來添加一個新的bin到貨架上,並且我添加了一些邏輯來確保它在被添加到貨架之前傳遞了一個Location對象(現在我在開發之前使用列表將所有內容移動到數據庫)。pythonic方式來檢查參數類型

但是我剛剛在一本Python書中讀到,我認爲在出現異常時通常會更好,而不是添加額外的代碼。我刪除了邏輯,看看我會得到什麼錯誤,但我沒有得到任何東西,它允許一個字符串代替Location對象。

是否有更強大的Pythonic方法來強制執行參數類型?

我有架子什麼:

class CrossDock: 
locations = [] 

def add_location(self, location): 
    if isinstance(location, Location): #if this is commented out it will take what ever is passed to it 
     self.locations.append(location) 
    else: 
     print("location parameter must be of type: Location. Parameter is of type" + str(type(location))) 

有沒有一種方法,我可以用一個try /做到這一點,除了塊?

+0

注:您的'locations'字段是類字段,而不是一個實例字段。所有'CrossDock'實例將共享相同的副本。爲了解決這個問題,定義一個'__init__'方法並在那裏設置'self.locations'。 – user2357112

+0

只有一個CrossDock的實例,我是否應該將位置字段放在__init__方法中? – IanAuld

+0

是的。它在概念上屬於這種情況;如果你想製作更多的CrossDock,你會希望他們有單獨的列表。 – user2357112

回答

4

將傳播異常傳播給調用者。這會迫使你的班級的用戶在他們誤用班級時修復無效類型。打印沒有用,因爲它不強制執行接口合同。

class CrossDock(object): 
    def __init__(self): 
     self.locations = [] 

    def add_location(self, location): 
     if isinstance(location, Location): 
      self.locations.append(location) 
     else: 
      raise TypeError("location must be Location, got: " + 
          repr(type(location))) 
+0

我認爲你有一些Java泄漏,並且你在'__init__'上丟失了括號。此外,不是一個錯誤,但我建議讓'CrossDock'從'object'繼承,所以它是一個新風格的類。 – user2357112

+0

我已經使Python per @ user2357112的評論有效,並將其更改爲引發更多慣用的'TypeError'。隨意回滾 – jfs

-2

使用assert在try內部/ except塊

class Location(): 
    pass 

class CrossDock: 
    locations = [] 

    def add_location(self, location): 
     try: 
      assert(isinstance(location, Location)) 
      self.locations.append(location) 
      print("added") 
     except AssertionError: 
      print("error: Parameter is of type" + str(type(location))) 


c = CrossDock() 
loc = Location() 
c.add_location("2") 
c.add_location(loc) 

將無法​​在第一add_location呼叫

location parameter must be of type: Location. Parameter is of type<type 'str'> 

added 
+0

斷言嚴格用於調試;它們不應該用於驗證屬於公共接口的方法的前提條件,因爲它們可以被禁用。此外,捕獲異常並打印錯誤消息比傳播它更有幫助。 – user2357112

+0

OP要求嘗試/除了這是爲什麼我發現異常。印刷是爲了示範,並符合OP問題中的行動。 –

+0

我有什麼作品,但我不確定是否是閱讀後的最佳方式。所以我有一些可行的方法,但我想知道它是否是/未來最好的方式。 – IanAuld

1

例外,你可能最終得到將代碼中的其他地方發生的,當你嘗試要使用Location實例,而是找到其他地方。檢查來自不可靠來源的參數時沒有任何問題。這將例外置於問題的根源上,而不是在診斷代碼中的次要位置時可能更難。

你可能會做幾乎你所擁有的,只會引發異常而不是打印錯誤。

def add_location(self, location): 
    if not isinstance(location, Location): 
     tmpl = "location parameter must be of type: Location, got %s" 
     raise TypeError(tmpl % str(type(location))) 
    ... do other processing here after guarding check ... 

這種類型的檢查,如果你有在調用代碼沒有控制是最合適的。如果你只是想抓住你做了自己一個編程錯誤,你可以只使用一個斷言:

def add_location(self, location): 
    assert isinstance(location, Location), "location must be of type: Location" 
    ... do other processing here 

反對這樣做參數類型檢查的建議是針對讓您的代碼中最大的靈活性,例如有人想要傳入一個與位置方法相同的對象。即使代碼可以工作,檢查硬編碼類型也會引發異常。

+0

啊,是的,好點。更新以反映。 – scanny

相關問題