简体   繁体   中英

python compare 2 similar objects with duck typing

Maybe my design is totally out of whack, but if I have 2 derived class objects that are comparable, but class D1 will basically always > class D2. (Say comparing Ivy Bridge to 286). How would I implement class D1's comparison to reflect that without using isinstance(D2)?

I saw this: Comparing two objects and If duck-typing in Python, should you test isinstance?

I could add a "type" attribute, and then compare the types, but then I might as well use isinstance. The easiest way would be to use isinstance... Any better suggestions?

I would ask myself "what is it about D2 that makes it always greater than D1?" In other words, do they have some common attribute that it would make sense to base the comparison off of. If there is no good answer for this question, it might be worth asking whether creating comparisons for these two objects actually make sense.

IF, after considering these things, you still think that doing the comparison is a good idea, then just use isinstance . There's a reason it still exists in the language -- and python is constantly deprecating things that are considered bad practice which implies that isinstance isn't always a bad thing.

The problem is when isinstance is used to do type checking unnecessarily. In other words, users often use it in a "Look before you leap" context which is completely unnecessary.

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

In this case, if the user doesn't put something that looks enough like a Foo into the function, it will raise an exception anyway. Why restrict it to only Foo objects? In your case however, it seems like the type of the objects actually matter from a conceptual standpoint. This is why isinstance exists (in my opinion).

I would do something like this:

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)
  • If D2 is a subtype of D1, instances of D2 will always compare less than instances of D1.
  • If D0 is a parent type of D1, instances of D0 will always compare greater than instances of D1.
  • If you compare an instance of D1 to another instance of D1, the comparison will be by the class's attributes.
  • If you compare an instance of D1 to an instance of an unknown class, the comparison will be by the class's attributes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM