Skip to content

Commit bb70707

Browse files
encukoublaisep
andcommitted
Continue Subscriptions and slicing
Co-authored-by: Blaise Pabon <blaise@gmail.com>
1 parent 7d892d3 commit bb70707

File tree

2 files changed

+59
-45
lines changed

2 files changed

+59
-45
lines changed

Doc/reference/datamodel.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ floating-point numbers. The same caveats apply as for floating-point numbers.
294294
The real and imaginary parts of a complex number ``z`` can be retrieved through
295295
the read-only attributes ``z.real`` and ``z.imag``.
296296

297+
.. _datamodel-sequences:
297298

298299
Sequences
299300
---------
@@ -465,6 +466,8 @@ Frozen sets
465466
a dictionary key.
466467

467468

469+
.. _datamodel-mappings:
470+
468471
Mappings
469472
--------
470473

Doc/reference/expressions.rst

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -949,54 +949,67 @@ Subscriptions and slicing
949949
pair: object; dictionary
950950
pair: sequence; item
951951

952-
The subscription of an instance of a :ref:`container class <sequence-types>`
953-
will generally select an element from the container.
954-
Subscripting a mapping will select a value using a key::
952+
:dfn:`Subscription` is an operation of selecting an element from a
953+
:ref:`container <sequence-types>`.
954+
The subscription syntax uses square brackets, which contain a :dfn:`key`,
955+
:dfn:`index` or :dfn:`slice` -- that is, an expression by which the requested
956+
element is looked up.
957+
For example, subscription is used to get a value from a
958+
:ref:`mapping <datamodel-mappings>` using a key, or to get an item from a
959+
:ref:`sequence <datamodel-sequences>` using an index::
955960

956961
>>> digits_by_name = {'one': 1, 'two': 2}
957962
>>> digits_by_name['two']
958963
2
959964

960-
Subscripting a sequence will select an item using an index::
961-
962965
>>> number_names = ['zero', 'one', 'two', 'three', 'four', 'five']
963966
>>> number_names[2]
964967
'two'
965968
>>> number_names[-2]
966969
'four'
967970

968-
The subscription of a :term:`generic class <generic type>` will generally
969-
return a :ref:`GenericAlias <types-genericalias>` object::
971+
The subscription syntax is also used to provide type arguments for
972+
:term:`generic types <generic type>`::
970973

971-
>>> list[str]
972-
list[str]
974+
>>> seq: list[str]
973975

974-
At the syntax level, all of these operations are equivalent.
975-
The object being subscribed must be a :ref:`primary <primaries>`.
976-
When it is subscripted, the interpreter will evaluate the primary and
977-
the the contents of the square brackets.
976+
Syntactically, the object being subscribed is a :ref:`primary <primaries>`.
977+
At runtime, the interpreter will evaluate the primary and
978+
the contents of the square brackets, and call the primary's
979+
:meth:`~object.__getitem__` or :meth:`~object.__class_getitem__` method.
980+
For more details on which of these methods is called, see
981+
:ref:`classgetitem-versus-getitem`.
978982

979-
The primary must evaluate to an object that supports subscription.
980-
An object may support subscription through defining one or both of
981-
:meth:`~object.__getitem__` and :meth:`~object.__class_getitem__`.
982-
For more details on when ``__class_getitem__`` is called instead of
983-
``__getitem__``, see :ref:`classgetitem-versus-getitem`.
983+
To show how subscription works, we can define a custom object that
984+
implements :meth:`~object.__getitem__` and prints out the key it
985+
was subscripted with::
984986

985-
In its simplest form, square brackets contain a single expression.
987+
>>> class SubscriptionDemo:
988+
... def __getitem__(self, key):
989+
... print(f'subscripted with: {key!r}')
990+
...
991+
>>> demo = SubscriptionDemo()
992+
>>> demo[1]
993+
subscripted with: 1
994+
995+
In the simplest form of subscription, the square brackets contain a single
996+
expression.
986997
The evaluated result of this expression will be passed to the
987-
:meth:`~object.__getitem__` or :meth:`~object.__getitem__` method.
998+
:meth:`~object.__getitem__` or :meth:`~object.__class_getitem__` method::
988999

989-
The square brackets can also contain up to three expressions separated by
990-
colons::
1000+
>>> demo[1 + 2]
1001+
subscripted with: 3
1002+
1003+
A more advanced form of subscription, :dfn:`slicing`, is commonly used
1004+
to extract a portion of a :ref:`sequence <datamodel-sequences>`.
1005+
In this form, the square brackets contain a :term:`slice`: up to three
1006+
expressions separated by colons.
1007+
Any of the expressions may be omitted, but a slice must contain at least one
1008+
colon::
9911009

9921010
>>> number_names = ['zero', 'one', 'two', 'three', 'four', 'five']
9931011
>>> number_names[1:3]
9941012
['one', 'two']
995-
996-
This form of subscription is called :term:`slicing`.
997-
Any of the expressions may be omitted, but at least one colon is necessary
998-
for this form::
999-
10001013
>>> number_names[1:]
10011014
['one', two', 'three', 'four', 'five']
10021015
>>> number_names[:3]
@@ -1006,35 +1019,27 @@ for this form::
10061019
>>> number_names[::2]
10071020
['zero', 'two', 'four']
10081021

1009-
When such a :term:`slice` is evaluated, the interpreter constructs a
1010-
:class:`slice` objects whose :attr:`~slice.start`, :attr:`~slice.stop` and
1022+
When a slice is evaluated, the interpreter constructs a :class:`slice` object
1023+
whose :attr:`~slice.start`, :attr:`~slice.stop` and
10111024
:attr:`~slice.step` attributes, respectively, are the results of the
10121025
expressions between the colons.
10131026
Any missing expression evaluates to :const:`None`.
10141027
This :class:`!slice` object is then passed to the :meth:`~object.__getitem__`
1015-
or :meth:`~object.__getitem__` method, as above.
1016-
1017-
For clarity, here is a custom object that prints out the key it was subscripted
1018-
with::
1028+
or :meth:`~object.__class_getitem__` method, as above. ::
10191029

1020-
>>> class SubscriptionDemo:
1021-
... def __getitem__(self, key):
1022-
... print(f'subscripted with: {key!r}')
1023-
...
1024-
>>> demo = SubscriptionDemo()
1025-
>>> demo[1]
1026-
subscripted with: 1
10271030
>>> demo[2:3]
10281031
subscripted with: slice(2, 3, None)
10291032
>>> demo[::'spam']
1030-
subscripted with slice(None, None, 'spam')
1033+
subscripted with: slice(None, None, 'spam')
10311034

1032-
The square brackets used for slicing can also contain two or more
1035+
The square brackets used for subscription can also contain two or more
10331036
comma-separated expressions or slices, or one expression or slice followed
10341037
by a comma.
1035-
In this case, the interpreter constructs a tuple of the results of the
1038+
This form is commonly used with numerical libraries for slicing
1039+
multi-dimensional data.
1040+
In this case, the interpreter constructs a :class:`tuple` of the results of the
10361041
expressions or slices, and passes this tuple to the :meth:`~object.__getitem__`
1037-
or :meth:`~object.__getitem__` method, as above::
1042+
or :meth:`~object.__class_getitem__` method, as above::
10381043

10391044
>>> demo[1, 2, 3]
10401045
subscripted with (1, 2, 3)
@@ -1043,11 +1048,17 @@ or :meth:`~object.__getitem__` method, as above::
10431048

10441049
The square brackets can also contain a starred expression.
10451050
In this case, the interpreter unpacks the result into a tuple, and passes
1046-
this tuple to :meth:`~object.__getitem__` or :meth:`~object.__getitem__`::
1051+
this tuple to :meth:`~object.__getitem__` or :meth:`~object.__class_getitem__`::
10471052

10481053
>>> demo[*range(10)]
10491054
subscripted with (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
10501055

1056+
Starred expressions may be combined with comma-separated expressions
1057+
and slices:::
1058+
1059+
>>> demo['a', 'b', *range(3), 'c']
1060+
subscripted with: ('a', 'b', 0, 1, 2, 'c')
1061+
10511062

10521063

10531064
.. grammar-snippet::

0 commit comments

Comments
 (0)