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:3maps toslice(1, 2, 3)1:2maps toslice(1, 2):maps toslice(None, None)1:maps toslice(1, None):1maps 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