Some comparisons are declared as not specified in Python 2.7:
The most important general rules for comparison are given in the Python Language Reference chapter 5. Expressions /5.9 Comparisons .
The first rules are numerical types (bool, int, long, float), strings (str, unicode), tuples and lists that are well known for comparison. The last two rules declare what is not specified:
- Mappings (dictionaries) are compared equal if and only if their sorted (key, values) lists are compared equal. [5] Results other than equality are resolved sequentially, but are not defined otherwise . [6]
- Most other objects of built-in types are compared unevenly if they are not the same object; the choice of whether one object is considered smaller or larger than another is made arbitrarily , but sequentially within the framework of one program execution .
Many special rules are contained in the Comparison chapter in the Python standard library / built-in views mentioned above in the question, and in documents about specific types, such as complex, decimal, or fractional.
Order comparisons are not supported for the complex type, and it should raise a TypeError. The decimal type is compared by value. It is compatible with numbers. Number since Python 2.7. fractions. The fraction is also compared by value.
My reflection: if the comparison relation can be arbitrary and cannot be reproduced in two executions of the program on one computer, then it is not useful to talk about transitivity. All of the above cases where the order is not explicitly specified in Python 2 should raise a TypeError in Python 3.
The transitivity or ordering of built-in types is known in Python 2.7, only between types where the values of different built-in types are equivalent, but they are not implemented equivalently to other types.
Example: broken transitivity in IronPython (inspired by Blender's comment and simplified):
>>> assert long(0) < 1.0 < [] < long(0) # 0 < 1; 'float' < 'list' < 'long'
Even equivalence ( == ), which looks simpler, is also not always transitive. This violates the transitivity of the operator ( <= ). See examples in the comments. (Thanks for the correction) (Equivalence is not an identity. a is b implies a == b , but not vice versa).
The examples use many trivial user classes with single-letter or lowercase names:
class A(object): pass class a(object): pass ... class z(object): pass
Observation - numbers
All numeric types have many naturally equivalent values in CPython and IronPython (and probably in all other implementations as per the docs)
>>> assert (False == 0 == 0L == 0.0 == 0 + 0j == Decimal('0') == Fraction(0, 1) < ... True == 1 == 1L == 1.0 == 1 + 0j == Decimal('1') == Fraction(1, 1))
Numeric types are ordered before all other types in CPython:
>>> assert 0 < 10**1000 < float('inf') < A() < Z() < a()
Numeric types are shared among other types in IronPython
>>> assert D() < decimal.Decimal('0') < E() >>> assert F() < fractions.Fraction(0, 1) < G() >>> assert b() < False < c() # bool >>> assert c() < 0 + 0j < d() # complex >>> assert f() < 0.0 < g() # float >>> assert i() < 0 < j() # int >>> assert l() < 0L < m() # long
Strings, etc.
str, bytearray and unicode have equivalent values
>>> assert bytearray('ab') == 'ab' == u'ab'
CPython in CPython doesn't use anything special when ordering other types,
>>> assert b() < bytearray('ab') < c() # bytearray >>> assert s() < 'ab' < t() # str >>> assert u() < u'ab' < v() # unicode in CPython
In IronPython: the unicode type behaves like str . This is not strange, because strings are implemented in .NET as unicode, and the same in IronPython.
>>> assert s() < u'ab' < t()