4

I recently came across this way of slicing a list in Python. I've never seen this one before, so I would like to understand this clearly.

I have a list ["Peter", "James", "Mark"] and if I slice it using the boolean value False it returns Peter and if I slice using True it returns James, as given below

  • ["Peter", "James", "Mark"][False] => Peter
  • ["Peter", "James", "Mark"][True] => James

I would like to know what happens here and what is this method called as?

Keyur Potdar
  • 6,949
  • 6
  • 25
  • 39
thileepan
  • 539
  • 2
  • 6
  • 18

2 Answers2

6

The datamodel hook here is the __index__ magic method:

>>> True.__index__()
1
>>> False.__index__()
0

The value returned by on obj's __index__ is used when accessing with subscripting, allowing arbitrary objects to be used with slices:

x[obj]

This is somewhat independent of the fact that bool is a subclass of int! You may achieve the same with any object.

>>> class A:
...     def __index__(self):
...         return 1
...     
>>> 'ab'[A()]
'b'

Whether __index__ is resolved for int subclasses depends on implementation detail.

CPython 3.7.1:

>>> class MyInt(int):
...     def __index__(self):
...         return 1
... 
>>> '01'[MyInt(0)]
'0'

PyPy 5.0.1:

>>>> class MyInt(int):
....     def __index__(self):
....         return 1
....         
>>>> '01'[MyInt(0)]
'1'

PyPy behaves correctly according to the Python datamodel. Looks like CPython is taking a shortcut / performance optimization.

wim
  • 302,178
  • 90
  • 548
  • 690
  • A `MyInt` is already an int, so Python doesn't actually need to perform a conversion to int. I'd say both results are consistent with the data model. – user2357112 Apr 05 '18 at 19:41
2

In Python, bool class is derived from of int Hence True=1 and False=0

print (True + True) will give an output 2

So on a list ['peter', 'john', 'abhi'][True] returns 2nd element of the list i.e. john

AB Abhi
  • 2,476
  • 22
  • 30