2017-10-13 148 views
2

對於某些情況下,我使用Doyren庫(libtcod)在Python中製作Roguelike遊戲。我更習慣於C++強對象類型的對象。什麼時候應該在Python中使用'assert'?

我寫了幾類,如GameMap,遊​​戲物體,等等。許多這些類的含有期望某些類型的方法,例如:

class GameMap: 
    ... 
    def add_object(self, game_object, x, y): 
     ... 

這種方法增加了遊戲對象game_object到座標(x,y)在地圖上。顯然有多種方式這個功能可以被濫用:

  • 非遊戲對象可以作爲game_object
  • 的非整數可以爲x或y
  • 負整數,可以作爲傳遞傳遞傳遞x或y
  • 一個整數,它超出了地圖的寬度可以爲x
  • 一個整數,它超出了地圖的高度可以爲y傳遞被傳遞

我的問題是這樣的:處理方法濫用的Pythonic方法是什麼?

我看到幾個可能性:

選項1:奠定了一系列的斷言在方法的開始:

def add_object(self, game_object, x, y): 
    assert(isinstance(game_object, GameObject) 
    assert(type(x) == type(y) == int) 
    assert(0 <= x < self.map_width and 0 <= y < self.map_height) 
    ... 

這些斷言得到相當重複的,因爲我複製+粘貼它們到我在GameMap中的許多方法中,這就是爲什麼我還提供選項2:

選項2:在自己的函數中編寫斷言,然後調用這些斷言需要防止當拷貝+粘貼

def check_game_object(self, game_object): 
    assert(isinstance(game_object, GameObject) 

def check_coordinate(self, x, y): 
    assert(type(x) == type(y) == int) 
    assert(0 <= x < self.map_width and 0 <= y < self.map_height) 

def add_object(self, game_object, x, y): 
    check_game_object(game_object) 
    check_coordinate(x, y) 
    ... 

選項3:鋪陳一系列自定義異常的在方法的開始:

def add_object(self, game_object, x, y): 
    if not isinstance(game_object, GameObject): 
     raise InvalidParameterException("game_object not a GameObject") 
    elif not type(x) == type(y) == int: 
     raise InvalidParameterException("(x, y) not integers") 
    elif not (0 <= x < self.map_width and 0 <= y < map.self_height) 
     raise InvalidMapCell("x, y do not represent a valid map cell) 
    ... 

選項4:返回失敗指示符,並在更高級別處理問題

def add_object(self, game_object, x, y): 
    if not isinstance(game_object, GameObject): 
     return False 
    elif not type(x) == type(y) == int: 
     return False 
    elif not (0 <= x < self.map_width and 0 <= y < map.self_height) 
     return False 
    ... 

選項X:別的嗎?

任何意見在這裏將不勝感激!當我繼續時,我想確保我遵循一個有用且可維護的模式。

+1

斷言是** **不驗證參數。它們用於確保外部非用戶對象符合預期。 –

+0

謝謝你的建議。是否有另一種Pythonic方法來強制使用正確的方法? – Ashley

+3

在Python中執行此操作的常用方法是僅使用該對象並捕獲任何生成的異常。 –

回答

1

斷言是爲了確保對象,結果,返回等是預期的。雖然它們可以用於變量的類型檢查,但這不是它們的真正目的,而是重複性的。

就你而言,我會建議使用python EAFP的方式做事。讓操作在函數輸入上執行,並在異常情況下捕捉異常。來自Python glossary

EAFP:容易要求寬恕而不是權限。這種常見的Python編碼風格假定存在有效的鍵或屬性,並且如果假設證明爲假,則捕獲異常。這種乾淨而快速的風格的特點是存在很多嘗試和除了 陳述。該技術與LBYL(三思而後行)常見的許多 其他語言風格形成鮮明對比,如C.

一個簡單的例子:

def f(x): 
    """If x is str a TypeError is raised""" 
    return 1 + x 

try: 
    f('a') 
except TypeError as e: 
    # something here or raise a custom exception 
    raise 
+0

非常感謝,這就是我以後的感受。 – Ashley

相關問題