2013-12-19 75 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

相关问题