On Wed, 20 Jul 2022 at 20:55, Frank Millman <fr...@chagford.com> wrote: > > On 2022-07-20 11:37 AM, Chris Angelico wrote: > > On Wed, 20 Jul 2022 at 18:34, Frank Millman <fr...@chagford.com> wrote: > >> > >> Hi all > >> > >> C:\Users\E7280>python > >> Python 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:19:38) [MSC v.1929 64 > >> bit (AMD64)] on win32 > >> Type "help", "copyright", "credits" or "license" for more information. > >> >>> > >> >>> x = list(range(10)) > >> >>> > >> >>> '{x[1]}'.format(**vars()) > >> '1' > >> >>> > >> >>> '{x[-1]}'.format(**vars()) > >> Traceback (most recent call last): > >> File "<stdin>", line 1, in <module> > >> TypeError: list indices must be integers or slices, not str > >> >>> > >> > >> Can anyone explain this error? It seems that a negative index is deemed > >> to be a string in this case. > >> > > > > Yeah, that does seem a little odd. What you're seeing is the same as > > this phenomenon: > > > >>>> "{x[1]} {x[spam]}".format(x={1: 42, "spam": "ham"}) > > '42 ham' > >>>> "{x[1]} {x[spam]}".format(x={"1": 42, "spam": "ham"}) > > Traceback (most recent call last): > > File "<stdin>", line 1, in <module> > > KeyError: 1 > > > > But I can't find it documented anywhere that digits-only means > > numeric. The best I can find is: > > > > https://docs.python.org/3/library/string.html#formatstrings > > """The arg_name can be followed by any number of index or attribute > > expressions. An expression of the form '.name' selects the named > > attribute using getattr(), while an expression of the form '[index]' > > does an index lookup using __getitem__().""" > > > > and in the corresponding grammar: > > > > field_name ::= arg_name ("." attribute_name | "[" element_index > > "]")* > > index_string ::= <any source character except "]"> + > > > > In other words, any sequence of characters counts as an argument, as > > long as it's not ambiguous. It doesn't seem to say that "all digits is > > interpreted as an integer, everything else is interpreted as a > > string". ISTM that a negative number should be interpreted as an > > integer too, but that might be a backward compatibility break. > > > > Thanks for investigating this further. I agree it seems odd. > > As quoted above, an expression of the form '[index]' does an index > lookup using __getitem()__. > > The only __getitem__() that I can find is in the operator module, and > that handles negative numbers just fine.
In general, __getitem__ is the method used to handle those sorts of lookups: class X: def __getitem__(self, item): print("Get item", type(item), item) "{x[0]} {x[1]} {x[-1]} {x[spam]} {x[1.0]}".format(x=X()) Outside of a format directive, you'd need to quote those: x[0], x[1], x["spam"] The distinction is that unquoted bare numbers are interpreted as integers, not as strings. I'm unable to find the exact definition of that documented. > Do you think it is worth me raising an issue, if only to find out the > rationale if there is one? > I'd wait for other people's responses first, there may be a better insight to be found than what I was able to come across. ChrisA -- https://mail.python.org/mailman/listinfo/python-list