Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Python允许序列使用超出范围的切片索引?_Python_Python 3.x_Sequence_Slice_Range Checking - Fatal编程技术网

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

为什么Python允许序列使用超出范围的切片索引?,python,python-3.x,sequence,slice,range-checking,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特性,并希望对此进行一些澄清

以下数组操作有些道理:

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做的一件奇怪的事情吗?
-它有目的吗?
-还是我的想法不对?

答案如下:

s[i:j]
:从
i
j
s
切片(注(4))

(4) 从
i
j
s
片段被定义为项目序列 索引
k
使
i成为关于超出范围索引的问题的一部分
切片逻辑自动将索引剪辑到序列的长度

为了方便起见,允许切片索引延伸超过端点。必须对每个表达式进行范围检查,然后手动调整限制,这将是一件痛苦的事情,因此Python会为您这样做

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

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

或者艰难的方式(自己做限额检查):

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

关于作业长度与输入长度不匹配的部分问题 OP还想知道允许分配的理由,例如分配目标的长度(80)与替换数据长度(2)不同的
p[20:100]=[7,8]

通过与字符串的类比,最容易看出动机。考虑,<代码>“五只小猴子”。替换(“小”,“Huungy”)< /代码>。请注意,目标“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

希望这些实际的例子能很好地解释为什么切片是这样工作的

我认为OP不是在问切片是如何工作的,他是在问设计选择背后的基本原理。@Primusa-我相信他们两个都在问。这解释了如何,这很好,因为它解释了为什么行为没有被破坏。“为什么”可能隐藏在某个邮件列表的深处。答案很好,但这并不能解释为什么新的数字会被附加到列表的末尾。@为了完整性,Atirag我添加了一个关于它的小广告。@Atirag索引与切片非常不同;索引总是引用值。“即使现在,我们在筛选[例如使用
s[:]
]时也使用它来更新列表”-您能否详细说明为什么要在那里使用
s[:]=
,而不是只使用
s=
?我从未见过有人在一行的上下文中使用
s[:]=
,比如你在那里写的内容。否则答案很好@Quuxplusone:Slice赋值使
s
已经引用的列表发生变异;使用
s=
重新绑定
s
以引用新列表。如果列表可以通过多个名称访问,并且您希望所有名称都能看到该变异,那么切片分配就是您想要的。另外,如果
s
是全局的,则重新分配
s
将需要一个
global
声明,但即使没有
global
语句,切片分配也会有类似的效果。在其他语言中,我总是到处写这种东西:
if I>sequence.length():return sequence.slice(0,sequence.length())else sequence.slice(0,n)
这与在Python中仅使用
sequence[:n]
完全相同。它为您节省了一条if语句和对
length
.BTW的两个调用。您可以将切片视为“集”。因此
p[20:22]
是索引介于20和22之间的所有元素的序列。空集是有效集。这与说
p[20]不同
它断言存在索引为20的元素。因此,查找元素和片段之间的范围检查差异反映了两种不同的含义。我认为这是一个更广泛的问题,即为什么Python允许在不同长度的序列片段中添加序列,以及它的好处是什么。另一个问题是estion根本没有解决这个问题的赋值部分,它只是讨论了切片。
>>> s = list("five little monkeys")
>>> i = s.index('l')
>>> n = len('little')
>>> s[i : i+n ] = list("humongous")
>>> ''.join(s)
'five humongous monkeys'
s[:] = []           # clear a list
t = u[:]            # copy a list
s[:] = [x for x in s if not math.isnan(x)]   # filter-out NaN values