2

在单个字符串中,当我尝试获取第二个字符时,python 非常冗长地失败,这是正确且预期的行为。

print 'a'[1]

但是,当我尝试获取无效的子序列范围时,它会默默地失败。

print 'a'[1:]

行为差异的原因是什么?

4

5 回答 5

4

实际上永远不会在and的情况下slicing生成任何:errorstringslists

例如。

>>> s='abc'
>>> s[-1000:1000]
'abc'

工作正常。

另一方面,虽然Indexes未定义的访问将始终IndexError在两者中引发一个stringslists

>>> s[4]
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    s[4]
IndexError: string index out of range
于 2012-06-07T03:54:37.583 回答
2

当您查看列表上的可变切片的行为时,这更有意义:

>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[10] = 2
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    a[10] = 2
IndexError: list assignment index out of range
>>> a[10:] = [1, 2, 3]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3]

修改结束后的切片会将新值附加到末尾,相当于做a.extend([1, 2, 3])(尽管如果您的起点存在,则略有不同)。一旦您了解情况,这并不奇怪:

>>> a = list(range(10))
>>> a[2:4] = range(10)
>>> a
[0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9]

但是,由于您可以修改此切片,因此尝试将其访问为IndexError- 语言中没有其他任何地方可以使用除 a 之外的任何内容来设置失败,这会有点令人惊讶NameError。但是,NameError在这里没有意义 - Python找到了一个具有正确名称的对象,并在其上调用了一个方法。

因此,Python 不会将过去的切片视为列表错误。考虑到这一点,为什么访问切片在内置序列之间的行为会有所不同?字符串(和元组)是不可变的,所以切片分配总是会失败——但是看看有什么值是没有突变的。

所以,真的,最终的原因是 - 这是因为开发人员认为这种行为没有其他可能的行为那么令人惊讶。

于 2012-06-07T04:24:06.957 回答
1

语义不同:

 print 'a'[1]

试图索引到一个不存在(即无效)的索引/位置,这一个错误。

 print 'a'[1:]

根据指定的范围简单地返回一个空字符串 ( ''),这不是错误。

IE,

In [175]: 'a'[1]
---------------------------------------------------------------------------
----> 1 'a'[1]
IndexError: string index out of range


In [176]: 'a'[1:]
Out[176]: ''
于 2012-06-07T03:49:44.347 回答
1

切片操作不同于索引操作。索引返回一个元素,切片返回一个范围,甚至是空范围或空字符串。

具有单个元素的数组有两个“边界”,其中索引指针可以是:0 和 1。您可以切片,您将'a'[0:1]获得位于这些位置之间的字符串(或列表或数组中的范围)。

如果你从最左边的边界切到最后,读数会走到最后,它已经在哪里,你会得到空字符串。

于 2012-06-07T03:55:15.117 回答
0

可以这样想:

当您使用a[1]时,假定您确切知道要访问的内容(在这种情况下 - 字符串中的第二个元素)。由于a[1]不存在 python 引发异常。

但是,范围运算符a[1:]是用可能不知道数据的确切范围的语义实现的,因此即使您指定的索引非常大(随机猜测),您仍然会得到字符串(或序列)的有效部分。在这种情况下你得到一个空字符串的原因是这个范围内的字符串中没有元素a[1:]

希望这可以帮助。

于 2012-06-07T04:38:17.300 回答