Title: Can't subscript objects with the string "1" using str.format()
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.9
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: Dennis Sweeney, efbqenb, eric.smith, ezio.melotti
Priority: normal Keywords:

Created on 2021-07-20 12:58 by efbqenb, last changed 2021-08-04 15:51 by eric.smith. This issue is now closed.

Messages (3)
msg397867 - (view) Author: Efbqenb (efbqenb) Date: 2021-07-20 12:58
The formatting does not work correctly.

I have a dict with string representations of integers as keys, such as {'1': 'a'} and trying to format it this way: '{0[1]}' and KeyError occurs. But I think it should not as '{0[a]}'.format(a) works properly with a = {'a': '1'} and '{0[1]}'.format(a) works properly with a = {1: 'a'}. Adding quotation marks does not help, KeyError occurs with '"1"'.
msg397883 - (view) Author: Dennis Sweeney (Dennis Sweeney) * (Python triager) Date: 2021-07-20 15:59
If I understand correctly, this shows the behavior you're objecting to:

>>> class A:
...     def __getitem__(self, key):
...         print(f"{key = }")
...         return "apple"
>>> '{0[1]}'.format(A()) # passes an integer
key = 1
>>> '{0[apple]}'.format(A()) # passes a string
key = 'apple'
>>> '{0["1"]}'.format(A()) # passes the length-3 string including double-quotes
key = '"1"'

There's no clear way to use str.format() to get the value for the string key "1". However, I don't think it makes sense to backwards-incompatibly change the behavior to pass the string "1" instead of the integer 1, since a common use is indexing with integers like

    >>> "{0[0]}{0[2]}{0[4]}".format(("a", "b", "c, "d", "e"))

This is an edge case, but it is aligned with the specification: according to,

    """Because arg_name is not quote-delimited, it is not possible to specify arbitrary dictionary keys (e.g., the strings '10' or ':-]') within a format string."""
msg397890 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2021-07-20 18:02
Yes, this is a "feature" of str.format. If it looks like a number, it's converted to a number, else it's used as a string. It's generally the most useful way to interpret subscripts, but as you note it doesn't handle all cases.
Date User Action Args
2021-08-04 15:51:57eric.smithsetcomponents: + Interpreter Core, - Unicode
2021-08-04 15:39:42vstinnersetnosy: - vstinner
2021-07-20 18:02:14eric.smithsetstatus: open -> closed

nosy: + eric.smith
messages: + msg397890

resolution: wont fix
stage: resolved
2021-07-20 16:04:44Dennis Sweeneysettitle: String formatting -> Can't subscript objects with the string "1" using str.format()
2021-07-20 15:59:56Dennis Sweeneysetnosy: + Dennis Sweeney
messages: + msg397883
2021-07-20 13:10:42efbqenbsetfiles: - 1.png
2021-07-20 12:58:24efbqenbcreate