2017-10-13 105 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

相关问题