class X:
def __bool__(self):
return True
x = [1, 2, 3]
x.sort(reverse=X())
print(x)
print(sorted([1, 2, 3], reverse=X()))
TypeError: an integer is required (got type X)
We can always still do
x.sort(reverse=bool(X()))
print(sorted([1, 2, 3], reverse=bool(X())))
but that isn't cool
I haven't looked at the source yet, but from experimentation I'm finding it rather hard to guess what the rules are for what works and what doesn't:
Python 3.7.3 (default, Mar 30 2019, 03:37:43)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import decimal, fractions, numpy
>>> sorted([1, 2, 3], reverse=0.5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: integer argument expected, got float
>>> sorted([1, 2, 3], reverse=decimal.Decimal(0.5))
[1, 2, 3]
>>> sorted([1, 2, 3], reverse=fractions.Fraction(0.5))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an integer is required (got type Fraction)
>>> sorted([1, 2, 3], reverse=numpy.int64(1))
[3, 2, 1]
>>> sorted([1, 2, 3], reverse=numpy.bool_(True))
[3, 2, 1]
> I'm finding it rather hard to guess what the rules are for what works and what doesn't
So now that I've looked at the source: anything with an `__int__` method works, except that `float` instances are explicitly excluded. So this explains for example:
>>> sorted([1, 2, 3], reverse=numpy.float64(0.5))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: integer argument expected, got float
>>> sorted([1, 2, 3], reverse=numpy.float32(0.5))
[1, 2, 3]
Not a bug. Both function docs say "reverse is a boolean value."
https://docs.python.org/3/library/stdtypes.html#boolean-values
says "Boolean values are the two constant objects False and True." These should be used in new code.
For compatibility with old code, CPython generally allows 0 and 1. In this case, it allows any 'integral value', but I would not necessarily expect this of other implementations.
[In general, the *Python language* docs do not document extra latitude allowed by the *CPython implementation*. So the lack thereof here is also not a bug.]
All objects without fancy trickery have a __bool__ method, either inherited from *object* or overridden. This in no way makes all such objects, including Xs, into boolean values.