切片操作实际上在python中返回什么

时间:2017-12-30 18:55:53

标签: python slice

“所有切片操作都返回一个包含所请求元素的新列表” 这是来自python教程。

但如果是这种情况,那么为什么这段代码会这样:

>>> a = [11, 3, 1999]
>>> a[:] = [9, 78]
>>> a
    [9, 78]

1)如果切片返回一个新列表,那么我为什么对新的绑定会影响原始绑定。这表明了什么?

但后来我也观察到了这一点:

>>> b = [4, 5, 6]
>>> b[:].append(5)
>>> b
[4, 5, 6]
>>> print(b)
[4, 5, 6]

2)这表明确实返回了一个新列表。切片列表时真正发生了什么?

请指出我的无知。提前谢谢。

1 个答案:

答案 0 :(得分:4)

您将表达式赋值混淆。获取值(读取)的处理方式与设置值(写入)不同。

分配(设置)重用语法来指定目标。在a[:] = ...之类的作业中,a[:]是作业发生的目标。在表达式中使用a[:]会生成一个新列表。

换句话说:您有两种不同的语言语句,它们故意使用相同的语法。但它们仍然是截然不同的。

请参阅Assignment statements reference documentation

assignment_stmt ::=  (target_list "=")+ (starred_expression | yield_expression)
target_list     ::=  target ("," target)* [","]
target          ::=  identifier
                     | "(" [target_list] ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | slicing
                     | "*" target
     

[...]

     
      
  • 如果目标是切片:评估参考中的主表达式。它应该产生一个可变序列对象(例如列表)。分配的对象应该是相同类型的序列对象。接下来,评估下限和上限表达式,只要它们存在;默认值为零和序列的长度。边界应该评估为整数。如果任一边界为负数,则将序列的长度添加到其中。生成的边界被裁剪为介于零和序列的长度之间(包括端点)。 最后,要求序列对象将切片替换为指定序列的项目。切片的长度可能与指定序列的长度不同,因此如果目标序列允许,则改变目标序列的长度。
  •   

(大胆强调我的)。

将其与表达式参考文档中的Slicings section进行比较;在表达式中切片会产生slice() objectlist.__getitem__方法将其解释为对复制了匹配索引的新列表对象的请求。其他对象类型可以选择以不同方式解释切片对象。

请注意,第三个​​操作,del statement删除引用,包括切片。删除采用相同的target_list语法,并要求删除切片指示的索引。

这三项操作全部由object.__getitem__()(阅读),object.__setitem__()(写作)和object.__delitem__()(删除)钩子方法实现;每个操作的key参数都是slice()对象,但只有__getitem__才能返回任何内容。