python - 为什么 Python 允许序列的超出范围的切片索引?

标签 python python-3.x sequence slice range-checking

所以我刚刚发现了一个在我看来像是一个奇怪的 Python 功能,并希望得到一些澄清。

下面的数组操作有点道理:

p = [1,2,3]
p[3:] = [4] 
p = [1,2,3,4]

我想它实际上只是将这个值附加到末尾,对吗?
但是,为什么我可以这样做?

p[20:22] = [5,6]
p = [1,2,3,4,5,6]

更是如此:

p[20:100] = [7,8]
p = [1,2,3,4,5,6,7,8]

这似乎是错误的逻辑。看起来这应该会引发错误!

有什么解释吗?
-这只是 Python 做的一件奇怪的事情吗?
-有目的吗?
- 还是我想错了?

最佳答案

关于超出范围索引的部分问题

切片逻辑会自动将索引裁剪为序列的长度。

为了方便起见,允许切片索引延伸过去的端点。必须对每个表达式进行范围检查然后手动调整限制会很痛苦,因此 Python 会为您完成。

考虑希望显示不超过文本消息的前 50 个字符的用例。

简单的方法(Python 现在所做的):

preview = msg[:50]

或者困难的方式(自己做极限检查):

n = len(msg)
preview = msg[:50] if n > 50 else msg

手动实现调整端点的逻辑很容易忘记,容易出错(在两个地方更新 50),冗长且速度慢。 Python 将该逻辑移至其简洁、自动、快速且正确的内部结构。这是我喜欢 Python 的原因之一 :-)

关于分配长度与输入长度不匹配的部分问题

OP 还想知道允许分配诸如 p[20:100] = [7,8] 的基本原理,其中分配目标的长度 (80) 与替换数据不同长度 (2)。

用字符串类比最容易看出动机。考虑一下,“五只小猴子”.replace(“little”, “humongous”)。请注意,目标“little”只有六个字母,而“humongous”有九个。我们可以对列表做同样的事情:

>>> s = list("five little monkeys")
>>> i = s.index('l')
>>> n = len('little')
>>> s[i : i+n ] = list("humongous")
>>> ''.join(s)
'five humongous monkeys'

这一切都归结为方便。

在引入 copy()clear() 方法之前,这些方法曾经很流行:

s[:] = []           # clear a list
t = u[:]            # copy a list

即使是现在,我们在过滤时也使用它来更新列表:

s[:] = [x for x in s if not math.isnan(x)]   # filter-out NaN values

希望这些实际示例能够很好地说明切片为何如此有效。

关于python - 为什么 Python 允许序列的超出范围的切片索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54613753/

相关文章:

来自 h2o 的 Python data.table

python - ValueError at/posts/create/invalidliteral for int() with base 10 : 'create' in django Form

python - 在 Catplot 中叠加图像

python - 如何从 "class"HTML 标签中查找文本匹配?

sql - Oracle/PostgreSQL 中的序列在插入语句中没有 ID

python - <script> 与包含在 Django 模板中的比较

python - 持续处理子进程中的大量 stdout 和 stderr

java - 从 JAX-WS 生成 XSD 时如何避免 XSD 序列?

oracle - JBoss EAP 6.x 在主键上带有 Hibernate Oracle 序列重复值

python - python中递归函数的累积结果