Comparison operators vs “rich comparison” methods in Python

前端 未结 2 1557
广开言路
广开言路 2021-02-05 15:11

Can someone explain me the differences between the two. Are those normally equivalent ? Maybe I\'m completely wrong here, but I thought that each comparison operator was necessa

相关标签:
2条回答
  • 2021-02-05 15:40

    This is relying on the __cmp__ magic method, which is what the rich-comparison operators were meant to replace:

    >>> dict1 = {1:1}
    >>> dict2 = {2:2}
    >>> dict1.__cmp__
    <method-wrapper '__cmp__' of dict object at 0x10f075398>
    >>> dict1.__cmp__(dict2)
    -1
    

    As to the ordering logic, here is the Python 2.7 documentation:

    Mappings (instances of dict) compare equal if and only if they have equal (key, value) pairs. Equality comparison of the keys and values enforces reflexivity.

    Outcomes other than equality are resolved consistently, but are not otherwise defined.

    With a footnote:

    Earlier versions of Python used lexicographic comparison of the sorted (key, value) lists, but this was very expensive for the common case of comparing for equality. An even earlier version of Python compared dictionaries by identity only, but this caused surprises because people expected to be able to test a dictionary for emptiness by comparing it to {}.

    And, in Python 3.0, ordering has been simplified. This is from the documentation:

    The ordering comparison operators (<, <=, >=, >) raise a TypeError exception when the operands don’t have a meaningful natural ordering.

    builtin.sorted() and list.sort() no longer accept the cmp argument providing a comparison function. Use the key argument instead.

    The cmp() function should be treated as gone, and the __cmp__() special method is no longer supported. Use __lt__() for sorting, __eq__() with __hash__(), and other rich comparisons as needed. (If you really need the cmp() functionality, you could use the expression (a > b) - (a <> b) as the equivalent for cmp(a, b).)

    So, to be explicit, in Python 2, since the rich comparison operators are not implemented, dict objects will fall-back to __cmp__, from the data-model documentation:

    object.__cmp__(self, other)
    Called by comparison operations if rich comparison (see above) is not defined. Should return a negative integer if self < other, zero if self == other, a positive integer if self > other.

    0 讨论(0)
  • 2021-02-05 15:42

    Note for operator < versus __lt__:

    import types
    
    class A:
        def __lt__(self, other): return True
    
    def new_lt(self, other): return False
    
    a = A()
    print(a < a, a.__lt__(a))  # True True
    a.__lt__ = types.MethodType(new_lt, a)
    print(a < a, a.__lt__(a))  # True False
    A.__lt__ = types.MethodType(new_lt, A)
    print(a < a, a.__lt__(a))  # False False
    

    < calls __lt__ defined on class; __lt__ calls __lt__ defined on object.

    It's usually the same :) And it is totally delicious to use: A.__lt__ = new_lt

    0 讨论(0)
提交回复
热议问题