python比较2个类似的对象与鸭子打字

时间:2012-07-14 03:21:13

标签: python comparison duck-typing

也许我的设计完全没有问题,但是如果我有2个可比较的派生类对象,但是D1类基本上总是> D2级。 (比如将Ivy Bridge与286进行比较)。我如何实现D1类的比较以反映不使用isinstance(D2)?

我看到了这个: Comparing two objectsIf duck-typing in Python, should you test isinstance?

我可以添加一个“type”属性,然后比较类型,但是我不妨使用isinstance。最简单的方法是使用isinstance ...有更好的建议吗?

2 个答案:

答案 0 :(得分:2)

我会问自己“D2是什么让它总是大于D1?”换句话说,他们是否有一些共同的属性,将比较作为基础是有意义的。如果对这个问题没有好的答案,可能值得一问的是,为这两个对象创建比较是否真的有意义。

如果在考虑这些事情后,您仍然认为进行比较是一个好主意,那么只需使用isinstance。有一个原因它仍然存在于语言中 - 而且python一直在贬低被认为是不良实践的东西,这意味着isinstance并不总是坏事。

问题是当isinstance用于不必要地进行类型检查时。换句话说,用户经常在“先看你跳跃”的背景下使用它,这是完全没必要的。

if not isinstance(arg,Foo): 
   raise ValueError("I want a Foo")

在这种情况下,如果用户没有将看起来像Foo的东西放入函数中,那么无论如何都会引发异常。为什么要将它限制为只有Foo对象?然而,在你的情况下,从概念的角度看,对象的类型实际上很重要。这就是isinstance存在的原因(在我看来)。

答案 1 :(得分:1)

我会做这样的事情:

class D1(object):
   def __val_cmp(self, other):
      # compare by attributes here
      if self.attr < other.attr:
         return -1
      elif self.attr > other.attr:
         return 1
      return 0

   def __cmp__(self, other):
      greater = isinstance(other, type(self))
      lesser = isinstance(self, type(other))
      if greater and lesser:
         # same type so compare by attributes
         return self.__val_cmp(other)
      elif greater:
         return 1
      elif lesser:
         return -1
      else:
         # other type is not a parent or child type, so just compare by attributes
         return self.__val_cmp(other)
  • 如果D2是D1的子类型,则D2的实例将始终比D1的实例少。
  • 如果D0是D1的父类型,则D0的实例将始终比D1的实例大。
  • 如果将D1的实例与D1的另一个实例进行比较,则比较将按类的属性进行比较。
  • 如果将D1的实例与未知类的实例进行比较,则比较将按类的属性进行比较