当前位置: 首页 > 知识库问答 >
问题:

为什么“{x[1:3]}”。format(x=“asd”)`是否导致键入错误?

郎成龙
2023-03-14

考虑一下:

>>> '{x[1]}'.format(x="asd")
's'
>>> '{x[1:3]}'.format(x="asd")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: string indices must be integers

这种行为的原因可能是什么?

共有2个答案

夏侯鹏
2023-03-14

'{x[1]}'。格式(x=“asd”)这里的[1]语法不是“正常”字符串索引语法,即使在这种情况下它看起来是以同样的方式工作的。

它使用的是格式规范迷你语言。同样的机制允许传递对象并访问格式化字符串(例如'{x.name}'.format(x=some_object))中的任意属性。

这种“假”索引语法还允许将可索引对象传递到格式,并直接从格式化字符串中获取所需的元素

'{x[0]}'.format(x=('a', 'tuple'))
# 'a'
'{x[1]}'.format(x=('a', 'tuple'))
# 'tuple'

文件中对此的唯一参考(至少我能找到)是以下段落:

字段_name本身以数字或关键字的arg_name开头。如果它是一个数字,它指的是一个位置参数,如果它是一个关键字,它指的是一个命名的关键字参数。如果格式字符串中的数字arg_名称按顺序为0、1、2,…,则它们都可以省略(而不仅仅是部分),并且数字0、1、2,…将自动按顺序插入。由于arg_name不以引号分隔,因此无法在格式字符串中指定任意字典键(例如字符串“10”或“:-]”)。arg_名称后面可以跟任意数量的索引或属性表达式。“形式”的表达。name'使用getattr()选择命名属性,而形式为“[index]”的表达式使用\uuuu getitem\uuu()执行索引查找。

虽然它提到

而形式为“[index]”的表达式使用\uuu getitem\uuuu()进行索引查找。

它没有提到任何关于不支持切片语法的内容。

对我来说,这感觉像是文档中的一个疏忽,尤其是因为“{x[1:3]}”。format(x=“asd”)会生成这样一条隐秘的错误消息,而且由于\uuuu getitem\uuuuu已经支持切片,因此更是如此。

支嘉祥
2023-03-14

基于您的注释的实验,检查对象的__getitem__方法实际接收的值:

class C:
    def __getitem__(self, index):
        print(repr(index))

'{c[4]}'.format(c=C())
'{c[4:6]}'.format(c=C())
'{c[anything goes!@#$%^&]}'.format(c=C())
C()[4:6]

输出(在线试用!):

4
'4:6'
'anything goes!@#$%^&'
slice(4, 6, None)

因此,当4被转换为int时,4:6不会像通常的切片那样被转换为切片(4,6,无)。相反,它只是字符串'4:6'。这不是索引/切片字符串的有效类型,因此TypeError:字符串索引必须是整数

更新:

有记录吗?好我看不到什么真正清晰的东西,但@GACy20指出了一些微妙的东西。语法有这些规则

field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
element_index     ::=  digit+ | index_string
index_string      ::=  <any source character except "]"> +

我们的c[4:6]字段名,我们对元素索引部分4:6感兴趣。我认为如果数字有自己的规则和有意义的名称,就会更清楚:

field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
element_index     ::=  index_integer | index_string
index_integer     ::=  digit+
index_string      ::=  <any source character except "]"> +

我想说,使用index_integer和index_string将更清楚地表明digit转换为整数(而不是保留数字字符串),而

这就是说,从规则本身来看,也许我们应该思考“将数字大小写从任何字符大小写中分离出来的意义是什么?”我认为关键是要区别对待纯数字,大概是把它们转换成整数。或者文档的其他部分甚至指出,digitdigits通常被转换为整数。

 类似资料:
  • 在2006年的模糊C代码竞赛中。请解释sykes2。c 有一个语句“

  • 我正在使用WildFly Server 20. x. x. x在Spring mvc中实现异步方法,但当我想部署它时,由于@EnableAsync注释的实现而发生错误 我的异步配置: 声明@EnableAsync注释时,会发生错误 同一个应用程序已经部署在Tomcat、TomEE、Jetty Server中,并且一切正常,没有问题。

  • 为什么比快?我使用的是CPython 3.5.2。 我试着改变我提升的幂,看看它是怎么做的,例如,如果我提升x的10或16的幂,它会从30跳到35,但如果我提升10.0作为浮动,它只是在24.1~4左右移动。 我想这和浮点转换和2次方有关,但我真的不知道。

  • 我想知道为什么numpy中有一维的维度数组(length,1),也有一维的维数组(lendth,),没有第二个值。 我经常遇到这种情况,例如在使用< code>np.concatenate()时,这需要预先执行< code>reshape步骤(或者我可以直接使用< code > h stack /< code > v stack )。 我想不出这种行为可取的理由。有人能解释一下吗? 编辑:< br

  • 问题内容: 执行此操作后(幕后)会发生什么? 也就是说,当变量在一个语句中后增加并分配给它自己时?我编译并执行了这个。即使整个陈述之后仍然是7 。在我的书中,它说是递增的! 问题答案: 确实增加了。但是,你正在将 的旧值分配给它自己。 1.递增x并返回其旧值。 2. 将旧值分配回自己。 因此,最后将其分配回其初始值。

  • 问题内容: 考虑以下示例: 我不确定Java语言规范中是否有一项规定要加载变量的先前值以便与右侧()进行比较,该变量应按照方括号内的顺序进行计算。 为什么第一个表达式求值,而第二个表达式求值?我本来希望先被评估,然后再与自身()比较并返回。 这个问题与Java表达式中子表达式的求值顺序不同,因为这里绝对不是“子表达式”。需要 加载 它以进行比较,而不是对其进行“评估”。这个问题是特定于Java的,