In discussion of this answer we realized that tuples do not have a __reversed__
method. My guess was that creating the iterator would require mutating the tuple. And yet tuples play fine with reversed
. Why can't the approach used for reversed
be made to work for __reversed__
as well?
>>> foo = range(3)
>>> foo
[0, 1, 2]
>>> list(foo.__reversed__())
[2, 1, 0]
>>> foo
[0, 1, 2]
>>> bar = (0, 1, 2)
>>> list(bar.__reversed__())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute '__reversed__'
>>> reversed(bar)
<reversed object at 0x10603b310>
>>> tuple(reversed(bar))
(2, 1, 0)
According to the spec:
reversed(seq)
Return a reverse iterator. seq must be an object which has a
reversed() method or supports the sequence protocol (the __len__() method and the __getitem__() method with integer arguments starting at
0).
EDIT: well, I try to say it again (english is not my native language) - with example.
Some functions - I call them fun(object)
- can use object.__func__()
to do the job or they use other functions in object
if there is no object.__func__()
-
For example str()
- when you use str(object)
it calls object.__str__()
, but if there is no object.__str__()
then it calls object.__repr__()
.
So you can use str()
with object which has no __str__()
and still get some result.
-
Other example <
- when you use a < b
it tries to use a.__lt__()
but if there is no a.__lt__()
it tries to use a.__gt__()
(and maybe other functions too)
class MyClass():
def __str__(self):
return "MyClass: __str__"
def __repr__(self):
return "MyClass: __repl__"
#-------------------------
def __lt__(self, other):
return True
def __gt__(self, other):
return True
#-------------------------
a = MyClass()
b = MyClass()
print( str(a) )
print( a < b )
You can remove __str__
to get different result.
You can change True/False
in __lt__
and you can see that result is changed.
Then you can remove __lt__
and you can change True/False
in __gt__
and you see that result is changed again.