简体   繁体   中英

Using dictionaries and compound field format() with Integer key stored as String

If a dictionary has an integer key stored as a string {'0': 'foo'} how would you reference that in Compound Field Names using .format() ?

I get that it may be un-pythonic (and bad programming) to have a dict with such keys...but in this case, it's also not possible to use this way:

>>> a_dict = {0: 'int zero',
...           '0': 'string zero',
...           '0start': 'starts with zero'}
>>> a_dict
{0: 'int zero', '0': 'string zero', '0start': 'starts with zero'}
>>> a_dict[0]
'int zero'
>>> a_dict['0']
'string zero'
>>> " 0  is {0[0]}".format(a_dict)
' 0  is int zero'
>>> "'0' is {0['0']}".format(a_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: "'0'"
>>> "'0start' is {0[0start]}".format(a_dict)
"'0start' is starts with zero"

{0[0]}.format(a_dict) will always refer to the key int 0 even if there isn't one, so at least that's consistent:

>>> del a_dict[0]
>>> a_dict
{'0': 'string zero', '0start': 'starts with zero'}
>>> "{0[0]}".format(a_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 0L

(And yes, I know I could just do '%s' % a_dict['0'] if required.)

str.format , unlike eg "f-strings" , doesn't use the full parser. To pull out the relevant bits of the grammar :

replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
element_index     ::=  digit+ | index_string
index_string      ::=  <any source character except "]"> +

A field_name surrounded by square brackets is an element_index , which is either:

  1. one or more digits ( digit+ , like 0 - but only if they're all digits, which is why 0start falls into the second case); or
  2. a sequence of "any source character except "]"" .

Therefore for 0['0'] the field_name is "'0'" , not '0' .

... an expression of the form '[index]' does an index lookup using __getitem__() .

For "'0' is {0['0']}".format(a_dict) the replacement is a_dict.__getitem__("'0'") , and there's no way within the grammar to select the actual a_dict['0'] .

You cannot. You'd need to pass in an additional argument to format.

>>> "'0' is {0[0]} {1}".format(a_dict, a_dict['0'])

Edit: I figured out the problem. It is calling dict. getitem with the string "'0'", not '0' as expected. Therefore this is impossible. Sorry.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM