For the next post in my syntactic sugar series I want to cover subscriptions. It&aposs quite possible you&aposre not familiar with this formal term, but you are probably familiar with the syntax: the square brackets used for indexing lists and tuples (sequence[4]
), accessing the value of a specified dictionary (dictionary["key"]
), etc. To cover this topic we will break up into three parts: general subscriptions, slicing, and multiple arguments.
General subscriptions
A subscription can get, set, or delete items from a collection. These three operations have equivalent special methods called __getitem__
, __setitem__
, and __delitem__
, respectively. Due to the fact that if a subscription is done on an object that does not have an appropriate special method, we will re-implement the appropriate functions from the operator
module. All three functions take a similar approach, so I will just show how __getitem__
works and let you look at the source code for the other two functions.
def __getitem__(container, index, /):
"""Return the item in the container at the specified index."""
container_type = type(container)
try:
getitem_method = debuiltins._mro_getattr(container_type, "__getitem__")
except AttributeError:
raise TypeError(f"{container_type.__name__!r} object is not subscriptable")
return getitem_method(container, index)
Implementation of operator.__getitem__
The code:
- Gets the type of the container.
- Gets the
__getitem__
method from the type. - If the method doesn&apost exist, raise
TypeError
. - Otherwise call the method appropriately.
Slicing
The syntax for slicing maps to the slice
class&apos constructor where any empty value is represented by None
.
::
maps toslice(None, None, None)
1:2:3
maps toslice(1, 2, 3)
1:2
maps toslice(1, 2)
:
maps toslice(None, None)
1:
maps toslice(1, None)
:1
maps toslice(None, 1)
(maps toslice(1)
as well)
The slice object then gets passed into the appropriate special method, so x[1:2:3]
is the equivalent of type(x).__getitem__(x, slice(1, 2, 3))
.
Multiple arguments
If you don&apost work with the scientific stack and use packages like NumPy, you may not know that you can actually pass in multiple arguments when using the subscription syntax: [1, 2, 3]
. The key difference to a function call, though, is all of the values get bundled up into a tuple that gets passed in as the first argument to the appropriate special method. This translates x[1, 2, 3]
to type(x).__getitem__((1, 2, 3))
. This also means that passing in a tuple with the same values is no different: x[1, 2, 3] == x[(1, 2, 3)]
.
from Planet Python
via read more
No comments:
Post a Comment