Skip to content

Commit 7d892d3

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

File tree

3 files changed

+364
-293
lines changed

3 files changed

+364
-293
lines changed

Doc/reference/datamodel.rst

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,6 +3202,66 @@ through the object's keys; for sequences, it should iterate through the values.
32023202

32033203
.. method:: object.__getitem__(self, key)
32043204

3205+
<<<<
3206+
3207+
For built-in objects, there are two types of objects that support subscription
3208+
via :meth:`~object.__getitem__`:
3209+
3210+
1. Mappings. If the primary is a :term:`mapping`, the expression list must
3211+
evaluate to an object whose value is one of the keys of the mapping, and the
3212+
subscription selects the value in the mapping that corresponds to that key.
3213+
An example of a builtin mapping class is the :class:`dict` class.
3214+
2. Sequences. If the primary is a :term:`sequence`, the expression list must
3215+
evaluate to an :class:`int` or a :class:`slice` (as discussed in the
3216+
following section). Examples of builtin sequence classes include the
3217+
:class:`str`, :class:`list` and :class:`tuple` classes.
3218+
3219+
The formal syntax makes no special provision for negative indices in
3220+
:term:`sequences <sequence>`. However, built-in sequences all provide a :meth:`~object.__getitem__`
3221+
method that interprets negative indices by adding the length of the sequence
3222+
to the index so that, for example, ``x[-1]`` selects the last item of ``x``. The
3223+
resulting value must be a nonnegative integer less than the number of items in
3224+
the sequence, and the subscription selects the item whose index is that value
3225+
(counting from zero). Since the support for negative indices and slicing
3226+
occurs in the object's :meth:`~object.__getitem__` method, subclasses overriding
3227+
this method will need to explicitly add that support.
3228+
3229+
.. index::
3230+
single: character
3231+
pair: string; item
3232+
3233+
A :class:`string <str>` is a special kind of sequence whose items are
3234+
*characters*. A character is not a separate data type but a
3235+
string of exactly one character.
3236+
3237+
...
3238+
3239+
3240+
A slicing selects a range of items in a sequence object (e.g., a string, tuple
3241+
or list). Slicings may be used as expressions or as targets in assignment or
3242+
:keyword:`del` statements. The syntax for a slicing:
3243+
3244+
3245+
.. index::
3246+
single: start (slice object attribute)
3247+
single: stop (slice object attribute)
3248+
single: step (slice object attribute)
3249+
3250+
The semantics for a slicing are as follows. The primary is indexed (using the
3251+
same :meth:`~object.__getitem__` method as
3252+
normal subscription) with a key that is constructed from the slice list, as
3253+
follows. If the slice list contains at least one comma, the key is a tuple
3254+
containing the conversion of the slice items; otherwise, the conversion of the
3255+
lone slice item is the key. The conversion of a slice item that is an
3256+
expression is that expression. The conversion of a proper slice is a slice
3257+
object (see section :ref:`types`) whose :attr:`~slice.start`,
3258+
:attr:`~slice.stop` and :attr:`~slice.step` attributes are the values of the
3259+
expressions given as lower bound, upper bound and stride, respectively,
3260+
substituting ``None`` for missing expressions.
3261+
3262+
3263+
====
3264+
32053265
Called to implement evaluation of ``self[key]``. For :term:`sequence` types,
32063266
the accepted keys should be integers. Optionally, they may support
32073267
:class:`slice` objects as well. Negative index support is also optional.
@@ -3212,6 +3272,8 @@ through the object's keys; for sequences, it should iterate through the values.
32123272
:term:`mapping` types, if *key* is missing (not in the container),
32133273
:exc:`KeyError` should be raised.
32143274

3275+
>>>>>>
3276+
32153277
.. note::
32163278

32173279
:keyword:`for` loops expect that an :exc:`IndexError` will be raised for

Doc/reference/expressions.rst

Lines changed: 128 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ Primaries represent the most tightly bound operations of the language. Their
893893
syntax is:
894894

895895
.. productionlist:: python-grammar
896-
primary: `atom` | `attributeref` | `subscription` | `slicing` | `call`
896+
primary: `atom` | `attributeref` | `subscription` | `call`
897897

898898

899899
.. _attribute-references:
@@ -931,9 +931,10 @@ If an :exc:`AttributeError` is raised and the object has a :meth:`!__getattr__`
931931
method, that method is called as a fallback.
932932

933933
.. _subscriptions:
934+
.. _slicings:
934935

935-
Subscriptions
936-
-------------
936+
Subscriptions and slicing
937+
-------------------------
937938

938939
.. index::
939940
single: subscription
@@ -949,62 +950,138 @@ Subscriptions
949950
pair: sequence; item
950951

951952
The subscription of an instance of a :ref:`container class <sequence-types>`
952-
will generally select an element from the container. The subscription of a
953-
:term:`generic class <generic type>` will generally return a
954-
:ref:`GenericAlias <types-genericalias>` object.
953+
will generally select an element from the container.
954+
Subscripting a mapping will select a value using a key::
955955

956-
.. productionlist:: python-grammar
957-
subscription: `primary` "[" `flexible_expression_list` "]"
956+
>>> digits_by_name = {'one': 1, 'two': 2}
957+
>>> digits_by_name['two']
958+
2
958959

959-
When an object is subscripted, the interpreter will evaluate the primary and
960-
the expression list.
960+
Subscripting a sequence will select an item using an index::
961+
962+
>>> number_names = ['zero', 'one', 'two', 'three', 'four', 'five']
963+
>>> number_names[2]
964+
'two'
965+
>>> number_names[-2]
966+
'four'
967+
968+
The subscription of a :term:`generic class <generic type>` will generally
969+
return a :ref:`GenericAlias <types-genericalias>` object::
970+
971+
>>> list[str]
972+
list[str]
973+
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.
978+
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`.
984+
985+
In its simplest form, square brackets contain a single expression.
986+
The evaluated result of this expression will be passed to the
987+
:meth:`~object.__getitem__` or :meth:`~object.__getitem__` method.
988+
989+
The square brackets can also contain up to three expressions separated by
990+
colons::
991+
992+
>>> number_names = ['zero', 'one', 'two', 'three', 'four', 'five']
993+
>>> number_names[1:3]
994+
['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+
1000+
>>> number_names[1:]
1001+
['one', two', 'three', 'four', 'five']
1002+
>>> number_names[:3]
1003+
['zero', 'one', 'two']
1004+
>>> number_names[:]
1005+
['zero', 'one', 'two']
1006+
>>> number_names[::2]
1007+
['zero', 'two', 'four']
1008+
1009+
When such a :term:`slice` is evaluated, the interpreter constructs a
1010+
:class:`slice` objects whose :attr:`~slice.start`, :attr:`~slice.stop` and
1011+
:attr:`~slice.step` attributes, respectively, are the results of the
1012+
expressions between the colons.
1013+
Any missing expression evaluates to :const:`None`.
1014+
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::
1019+
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
1027+
>>> demo[2:3]
1028+
subscripted with: slice(2, 3, None)
1029+
>>> demo[::'spam']
1030+
subscripted with slice(None, None, 'spam')
9611031

962-
The primary must evaluate to an object that supports subscription. An object
963-
may support subscription through defining one or both of
964-
:meth:`~object.__getitem__` and :meth:`~object.__class_getitem__`. When the
965-
primary is subscripted, the evaluated result of the expression list will be
966-
passed to one of these methods. For more details on when ``__class_getitem__``
967-
is called instead of ``__getitem__``, see :ref:`classgetitem-versus-getitem`.
1032+
The square brackets used for slicing can also contain two or more
1033+
comma-separated expressions or slices, or one expression or slice followed
1034+
by a comma.
1035+
In this case, the interpreter constructs a tuple of the results of the
1036+
expressions or slices, and passes this tuple to the :meth:`~object.__getitem__`
1037+
or :meth:`~object.__getitem__` method, as above::
9681038

969-
If the expression list contains at least one comma, or if any of the expressions
970-
are starred, the expression list will evaluate to a :class:`tuple` containing
971-
the items of the expression list. Otherwise, the expression list will evaluate
972-
to the value of the list's sole member.
1039+
>>> demo[1, 2, 3]
1040+
subscripted with (1, 2, 3)
1041+
>>> demo['spam',]
1042+
subscripted with ('spam',)
1043+
1044+
The square brackets can also contain a starred expression.
1045+
In this case, the interpreter unpacks the result into a tuple, and passes
1046+
this tuple to :meth:`~object.__getitem__` or :meth:`~object.__getitem__`::
1047+
1048+
>>> demo[*range(10)]
1049+
subscripted with (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
9731050

974-
.. versionchanged:: 3.11
975-
Expressions in an expression list may be starred. See :pep:`646`.
976-
977-
For built-in objects, there are two types of objects that support subscription
978-
via :meth:`~object.__getitem__`:
979-
980-
1. Mappings. If the primary is a :term:`mapping`, the expression list must
981-
evaluate to an object whose value is one of the keys of the mapping, and the
982-
subscription selects the value in the mapping that corresponds to that key.
983-
An example of a builtin mapping class is the :class:`dict` class.
984-
2. Sequences. If the primary is a :term:`sequence`, the expression list must
985-
evaluate to an :class:`int` or a :class:`slice` (as discussed in the
986-
following section). Examples of builtin sequence classes include the
987-
:class:`str`, :class:`list` and :class:`tuple` classes.
988-
989-
The formal syntax makes no special provision for negative indices in
990-
:term:`sequences <sequence>`. However, built-in sequences all provide a :meth:`~object.__getitem__`
991-
method that interprets negative indices by adding the length of the sequence
992-
to the index so that, for example, ``x[-1]`` selects the last item of ``x``. The
993-
resulting value must be a nonnegative integer less than the number of items in
994-
the sequence, and the subscription selects the item whose index is that value
995-
(counting from zero). Since the support for negative indices and slicing
996-
occurs in the object's :meth:`~object.__getitem__` method, subclasses overriding
997-
this method will need to explicitly add that support.
9981051

999-
.. index::
1000-
single: character
1001-
pair: string; item
10021052

1003-
A :class:`string <str>` is a special kind of sequence whose items are
1004-
*characters*. A character is not a separate data type but a
1005-
string of exactly one character.
1053+
.. grammar-snippet::
1054+
:group: python-grammar
1055+
1056+
subscription: `primary` '[' `slices` ']'
1057+
slices: `slice` | `tuple_slices`
1058+
tuple_slices: ','.(slice | starred_expression)+ [',']
1059+
1060+
slice:
1061+
| proper_slice
1062+
| assignment_expression
1063+
10061064

1065+
If *slices* contains ony one unstarred *slice* without a trailing comma,
1066+
it will evaluate to the value of that *slice*.
1067+
Otherwise, *slices* will evaluate to a :class:`tuple` containing
1068+
the items of *slices*
10071069

1070+
.. grammar-snippet::
1071+
:group: python-grammar
1072+
1073+
proper_slice: [`lower_bound`] ":" [`upper_bound`] [ ":" [`stride`] ]
1074+
lower_bound: `expression`
1075+
upper_bound: `expression`
1076+
stride: `expression`
1077+
1078+
.. versionchanged:: 3.11
1079+
Expressions in *tuple_slices* may be starred. See :pep:`646`.
1080+
1081+
See :meth:`~object.__getitem__` documentation for how built-in types handle
1082+
subscription, including support for negative indices.
1083+
1084+
<<<
10081085
.. _slicings:
10091086

10101087
Slicings
@@ -1022,43 +1099,7 @@ Slicings
10221099
pair: object; tuple
10231100
pair: object; list
10241101

1025-
A slicing selects a range of items in a sequence object (e.g., a string, tuple
1026-
or list). Slicings may be used as expressions or as targets in assignment or
1027-
:keyword:`del` statements. The syntax for a slicing:
1028-
1029-
.. productionlist:: python-grammar
1030-
slicing: `primary` "[" `slice_list` "]"
1031-
slice_list: `slice_item` ("," `slice_item`)* [","]
1032-
slice_item: `expression` | `proper_slice`
1033-
proper_slice: [`lower_bound`] ":" [`upper_bound`] [ ":" [`stride`] ]
1034-
lower_bound: `expression`
1035-
upper_bound: `expression`
1036-
stride: `expression`
1037-
1038-
There is ambiguity in the formal syntax here: anything that looks like an
1039-
expression list also looks like a slice list, so any subscription can be
1040-
interpreted as a slicing. Rather than further complicating the syntax, this is
1041-
disambiguated by defining that in this case the interpretation as a subscription
1042-
takes priority over the interpretation as a slicing (this is the case if the
1043-
slice list contains no proper slice).
1044-
1045-
.. index::
1046-
single: start (slice object attribute)
1047-
single: stop (slice object attribute)
1048-
single: step (slice object attribute)
1049-
1050-
The semantics for a slicing are as follows. The primary is indexed (using the
1051-
same :meth:`~object.__getitem__` method as
1052-
normal subscription) with a key that is constructed from the slice list, as
1053-
follows. If the slice list contains at least one comma, the key is a tuple
1054-
containing the conversion of the slice items; otherwise, the conversion of the
1055-
lone slice item is the key. The conversion of a slice item that is an
1056-
expression is that expression. The conversion of a proper slice is a slice
1057-
object (see section :ref:`types`) whose :attr:`~slice.start`,
1058-
:attr:`~slice.stop` and :attr:`~slice.step` attributes are the values of the
1059-
expressions given as lower bound, upper bound and stride, respectively,
1060-
substituting ``None`` for missing expressions.
1061-
1102+
>>>
10621103

10631104
.. index::
10641105
pair: object; callable

0 commit comments

Comments
 (0)