8.7. Operator Accessor

8.7.1. SetUp

>>> from dataclasses import dataclass

8.7.2. Example

>>> @dataclass
... class Vector:
...     x: int
...     y: int
...
...     def __getitem__(self, item): ...
...     def __setitem__(self, key, value): ...
...     def __delitem__(self, item): ...
...
...     def __missing__(self, key): ...
...     def __call__(self, *args, **kwargs): ...

8.7.3. Use Case - 0x01

>>> text = 'Python'
>>> text[0]
'P'
>>> text.__getitem__(0)
'P'

8.7.4. Use Case - 0x02

>>> data = ['a', 'b', 'c']
>>> data[1] = 'x'
>>> data.__setitem__(1, 'x')
>>> data[1]
'x'
>>> data.__getitem__(1)
'x'

8.7.5. Use Case - 0x03

  • Integer indexing

>>> import numpy as np
>>>
>>> a = np.array([[1, 2, 3],
...               [4, 5, 6],
...               [7, 8, 9]])
>>> a[0]
array([1, 2, 3])
>>>
>>> a.__getitem__(0)
array([1, 2, 3])

Intuitive implementation:

>>> class ndarray:
...     def __getitem__(self, item):
...         if type(item) is int:
...             ...

8.7.6. Use Case - 0x04

  • Tuple of integers

>>> import numpy as np
>>>
>>> a = np.array([[1, 2, 3],
...               [4, 5, 6],
...               [7, 8, 9]])
>>> a[0,1]
2
>>>
>>> a.__getitem__((0,1))
2

Intuitive implementation:

>>> class ndarray:
...     def __getitem__(self, item):
...         if type(item) is tuple:
...             row = item[0]
...             col = item[1]
...             ...

8.7.7. Use Case - 0x05

  • Slice

>>> import numpy as np
>>>
>>> a = np.array([[1, 2, 3],
...               [4, 5, 6],
...               [7, 8, 9]])
>>> a[1:3]
array([[4, 5, 6],
       [7, 8, 9]])
>>>
>>> a.__getitem__(slice(1,3))
array([[4, 5, 6],
       [7, 8, 9]])
>>> a[:2]
array([[1, 2, 3],
       [4, 5, 6]])
>>>
>>> a.__getitem__(slice(None,2))
array([[1, 2, 3],
       [4, 5, 6]])
>>> a[::2]
array([[1, 2, 3],
       [7, 8, 9]])
>>>
>>> a.__getitem__(slice(None,None,2))
array([[1, 2, 3],
       [7, 8, 9]])

Intuitive implementation:

>>> class ndarray:
...     def __getitem__(self, item):
...         if type(item) is slice:
...             start = item.start
...             stop = item.stop
...             step = item.step
...             ...

8.7.8. Use Case - 0x06

  • List of integers

>>> import numpy as np
>>>
>>> a = np.array([[1, 2, 3],
...               [4, 5, 6],
...               [7, 8, 9]])
>>> a[[0,2]]
array([[1, 2, 3],
       [7, 8, 9]])
>>>
>>> a.__getitem__([0,2])
array([[1, 2, 3],
       [7, 8, 9]])

Intuitive implementation:

>>> class ndarray:
...     def __getitem__(self, item):
...         if type(item) is list:
...             if type(item[0]) is int:
...                 ...

8.7.9. Use Case - 0x07

  • List of booleans

>>> import numpy as np
>>>
>>> a = np.array([[1, 2, 3],
...               [4, 5, 6],
...               [7, 8, 9]])
>>> a[[True,False,True]]
array([[1, 2, 3],
       [7, 8, 9]])
>>>
>>> a.__getitem__([True,False,True])
array([[1, 2, 3],
       [7, 8, 9]])

Intuitive implementation:

>>> class ndarray:
...     def __getitem__(self, item):
...         if type(item) is list:
...             if type(item[0]) is bool:
...                 ...

8.7.10. Use Case 0x08

  • Tuple of slice and integer

>>> import numpy as np
>>>
>>> a = np.array([[1, 2, 3],
...               [4, 5, 6],
...               [7, 8, 9]])
>>> a[:2, 1]
array([2, 5])
>>>
>>> a.__getitem__((slice(None,2), 1))
array([2, 5])
>>> class ndarray:
...     def __getitem__(self, item):
...         if type(item) is tuple:
...             rows = item[0]
...             cols = item[1]
...             if type(rows) is slice:
...                ...
...             if type(cols) is int:
...                ...

8.7.11. Use Case 0x09

>>> import numpy as np
>>>
>>> a = np.array([[1, 2, 3],
...               [4, 5, 6],
...               [7, 8, 9]])
>>> del a[1]
>>> a.__delitem__(1)

8.7.12. Use Case 0x0A

>>> import numpy as np
>>>
>>> a = np.array([[1, 2, 3],
...               [4, 5, 6],
...               [7, 8, 9]])
>>> a[0,1] = 10
>>> a.__setitem__((0,1), 10)

8.7.13. Use Case 0x0B

>>> class mydict(dict):
...     pass
>>>
>>>
>>> data = mydict()
>>> data['x']
Traceback (most recent call last):
KeyError: 'x'
>>> class mydict(dict):
...     def __missing__(self, key):
...         self[key] = None
>>>
>>>
>>> data = mydict()
>>>
>>> data['x']
>>> data
{'x': None}
>>>
>>> data['y']
>>> data
{'x': None, 'y': None}

8.7.14. Use Case 0x0C

>>> class mystr(str):
...     pass
>>>
>>>
>>> a = mystr('hello')
>>>
>>> callable(a)
False
>>>
>>> a()
Traceback (most recent call last):
TypeError: 'str' object is not callable
>>> class mystr(str):
...     def __call__(self):
...         print('calling')
...
>>>
>>> b = mystr('hello')
>>>
>>> callable(b)
True
>>>
>>> b()
calling