python - 为什么 Python 允许序列的超出范围的切片索引?
问题描述
所以我刚刚发现了一个在我看来像是一个奇怪的 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)不同。
用字符串类比最容易看出动机。考虑,"five little monkeys".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
希望这些实际示例能够很好地说明切片为何如此有效。
推荐阅读
- git - 如何在 Git 2.9 之前 git 合并不相关的历史记录(--allow-unrelated-histories 不可用)
- c++ - OpenCV C++ 中的小星球全景图
- c - fmodf() 是否会导致 stm32 出现硬故障?
- javascript - 如何使用`switch`获取上个月的名称?
- ruby-on-rails - 使用 RubyRails 应用程序根据发票添加付款的 quickbooks api
- java - fluentbit 将 java stacktrace 日志的每一行报告为新的日志事件
- python - 使用 Pandas Dataframe 制作颜色托盘
- spring-boot - 如何使 Spring Tool Suite 像一个多 Maven 模块项目?
- django - 在删除记录时在 Django Admin 中显示自定义消息
- python - 获取使用分页(限制,偏移)的SqlAlchemy查询结果的总记录数