在Python中,负索引的str.format(list)不起作用
我在替换字段中使用了负数索引来输出一个格式化的列表,但这引发了一个类型错误。代码如下:
>>> a=[1,2,3] >>> a[2] 3 >>> a[-1] 3 >>> 'The last:{0[2]}'.format(a) 'The last:3' >>> 'The last:{0[-1]}'.format(a) Traceback (most recent call last): File "", line 1, in TypeError: list indices must be integers, not str
5 个回答
没错,这个方法不行。解决办法是:
>>> 'The last:{0}'.format(a[-1])
'The last:3'
这里有几个问题,一旦你开始深入了解,就会发现:
我们讨论的这个东西叫做“element_index”,它被定义为一个整数。
问题1:除非用户点击“整数”的链接去查看语言参考手册,否则他们不会知道-1被认为是一个表达式,而不是一个整数。顺便说一下,任何想说“按文档说明工作”的人,最好先看看问题7 :-)
推荐的解决方案:改变定义,让“element_index”可以在整数前面加一个可选的'-'。
它是一个整数,对吧?别急……后面的文档说“形如'[index]'的表达式会使用 __getitem__()
进行索引查找。”
问题3:应该说'[element_index]'(index没有定义)。
问题4:并不是每个人都知道 __getitem__()
是干什么的。文档需要更清晰。
所以我们可以在这里使用字典和整数,对吧?是的,但也有一两个问题:
element_index是一个整数?是的,这在字典中是可以的:
>>> "{0[2]}".format({2: 'int2'})
'int2'
看来我们也可以使用非整数的字符串,但这需要更明确的文档(问题5):
>>> "{0[foo]}".format({'foo': 'bar'})
'bar'
但是我们不能用像'2'这样的键来使用字典(问题6):
>>> "{0[2]}".format({'2': 'str2'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 2
>>> "{0['2']}".format({'2': 'str2'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: "'2'"
问题7:那个“整数”其实应该记录为“十进制整数”……0x22和0b11被当作字符串处理,而010(一个“八进制整数”)被当作10,而不是8:
>>> "{0[010]}".format('0123456789abcdef')
'a'
更新: PEP 3101 讲述了真实的故事:
"""
解析项键的规则非常简单。如果它以数字开头,那么它被视为数字,否则它被当作字符串使用。
因为键没有用引号括起来,所以无法在格式字符串中指定任意字典键(例如,字符串“10”或“:-]”)。
"""
我觉得这在格式字符串的规范中算是一个设计上的小问题。根据文档,
element_index ::= integer | index_string
但是,遗憾的是,-1
并不是“一个整数”——它其实是一个表达式。单目负号的优先级并不高,所以比如说,print(-2**2)
会输出-4
——这也是一个常见的问题,可以说是设计上的小缺陷(因为**
这个运算符的优先级更高,所以先进行幂运算,然后再进行负号的操作)。
在格式字符串中,如果这个位置的内容不是整数(比如说是一个表达式),它会被当作字符串来处理,用来索引一个字典参数——例如:
$ python3 -c "print('The last:{0[2+2]}'.format({'2+2': 23}))"
The last:23
我不确定这是否值得在Python的跟踪系统中提出问题,但这确实是一个有点让人意外的行为:-(。