为什么 Python 允许序列的超出范围的切片索引? [英] Why does Python allow out-of-range slice indexes for sequences?

查看:58
本文介绍了为什么 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)预览 = msg[:50] 如果 n >50 其他消息

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

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

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

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

<预><代码>>>>s = list("五只小猴子")>>>i = s.index('l')>>>n = len('小')>>>s[i : i+n ] = list("巨大的")>>>''.join(s)五只巨大的猴子"

这一切都归结为方便.

在引入 copy()clear() 方法之前,这些曾经是流行的习惯用法:

s[:] = [] # 清空一个列表t = u[:] # 复制一个列表

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

s[:] = [x for x in s if not math.isnan(x)] # 过滤掉 NaN 值

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

So I just came across what seems to me like a strange Python feature and wanted some clarification about it.

The following array manipulation somewhat makes sense:

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

I imagine it is actually just appending this value to the end, correct?
Why can I do this, however?

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

And even more so this:

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

This just seems like wrong logic. It seems like this should throw an error!

Any explanation?
-Is it just a weird thing Python does?
-Is there a purpose to it?
-Or am I thinking about this the wrong way?

解决方案

Part of question regarding out-of-range indices

Slice logic automatically clips the indices to the length of the sequence.

Allowing slice indices to extend past end points was done for convenience. It would be a pain to have to range check every expression and then adjust the limits manually, so Python does it for you.

Consider the use case of wanting to display no more than the first 50 characters of a text message.

The easy way (what Python does now):

preview = msg[:50]

Or the hard way (do the limit checks yourself):

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

Manually implementing that logic for adjustment of end points would be easy to forget, would be easy to get wrong (updating the 50 in two places), would be wordy, and would be slow. Python moves that logic to its internals where it is succint, automatic, fast, and correct. This is one of the reasons I love Python :-)

Part of question regarding assignments length mismatch from input length

The OP also wanted to know the rationale for allowing assignments such as p[20:100] = [7,8] where the assignment target has a different length (80) than the replacement data length (2).

It's easiest to see the motivation by an analogy with strings. Consider, "five little monkeys".replace("little", "humongous"). Note that the target "little" has only six letters and "humongous" has nine. We can do the same with lists:

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

This all comes down to convenience.

Prior to the introduction of the copy() and clear() methods, these used to be popular idioms:

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

Even now, we use this to update lists when filtering:

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

Hope these practical examples give a good perspective on why slicing works as it does.

这篇关于为什么 Python 允许序列的超出范围的切片索引?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆