What are built-in Python 3 types that can be compared to each other?

别来无恙 提交于 2021-02-10 14:37:04

问题


In Python 2, it was possible to compare objects of different types such as int to str by having an implicit comparison of the text string of types (that is, in lexicographic order, string 'int' is less than string 'str' and string 'list' is less than string 'tuple').

Hence, in Python 2, 5 < 'hello' returns True. One can read more about why this was allowed in answer to Why is ''>0 True in Python?.

In Python 3, this raises builtins.TypeError: unorderable types: int() < str() exception.

This web page says

The strict approach to comparing in Python 3 makes it generally impossible to compare different types of objects.

Does it mean there are some built-in types or special cases where it would be possible for any built-in types to be compared without causing TypeError? I am not talking about custom types where the necessary dunder methods are implemented to properly support comparison.


回答1:


All these are valid statements (and they all evaluate to True):

0 < True
0 < 1.
0. < True
{0} < frozenset((0, 1))

The only thing that may look odd here is that 0. == False and 1. == True.

On the other hand, you can still reproduce what python 2 does by casting your value to an str before comparing it (this also evaluate to True):

str(5) < 'hello'

If you really need this behaviour you can always have a function that will cast/compare. That way you'll guarantee that objects of different types will always compare the same way, which seems to be the only constraint in python 2.

def lt(a, b):
    return str(a) < str(b)

Or maybe even better, you can cast only when needed:

def lt(a, b):
  try: 
    return a < b
  except TypeError: 
    return str(a) < str(b)

On the other hand, as suggested in the comments, in CPython's implementation, it seems like comparison is done in the following way:

def lt(a, b):
  try: 
    return a < b
  except TypeError: 
    if a is None:
      return True
    if b is None: 
      return False
    if isinstance(a, numbers.Number):
      return True
    if isinstance(b, numbers.Number):
      return False
    return str(type(a)) < str(type(b))



回答2:


I had already looked this up on the web before, and it appears they are indeed unsortable in Python 3, apart from the few special cases mentionned above.

The change usually manifests itself in sorting lists: in Python 3, lists with items of different types are generally not sortable. If you need to sort heterogeneous lists, or compare different types of objects, implement a key function to fully describe how disparate types should be ordered.
Source

I don't know why, but some found ways to reproduce the behavior of Python 2 using Python 3.

Maybe you should take a look at this or that. This question also highlighted the change in 2011:

Found it: Buried in PEP 3100: "Comparisons other than == and != between disparate types will raise an exception unless explicitly supported by the type"



来源:https://stackoverflow.com/questions/55694996/what-are-built-in-python-3-types-that-can-be-compared-to-each-other

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!