2019独角兽企业重金招聘Python工程师标准>>>
go有切片slice类型,python有列表和元组,这两种语言都有切片操作。
但是它们的切片操作是完全不同的。
首先说第一个,go的切片,其成员是相同类型的,python的列表和元组则不限制类型。
两种语言都有[a:b]这种切片操作,意义也类似,但是go的a、b两个参数不能是负数,python可以是负数,此时就相当于从末尾往前数。
两种语言都有[a:b:c]这种切片操作,意义却是完全不同的。go的c,表示的是容量;而python的c表示的是步长。
但是最大的不同,还是:
python的切片产生的是新的对象,对新对象的成员的操作不影响旧对象;go的切片产生的是旧对象一部分的引用,对其成员的操作会影响旧对象。
究其原因,还是底层实现的不同。
go的切片,底层是一个三元组,一个指针,一个长度,一个容量。指针指向一块连续的内存,长度是已有成员数,容量是最大成员数。切片时,一般并不会申请新的内存,而是对原指针进行移动,然后和新的长度、容量组成一个切片类型值返回。也就是说,go的切片操作通常会和生成该切片的切片共用内存。
不仅是切片,字符串、数组的切片也是一样的,通常会共用内存。
当然也有异常情况,那就是切片时,提供的容量过大,此时会申请新内存并拷贝;或者对切片append超出容量,也会如此。这时,新的切片,才不会和老切片共享内存。(如果你切片/创建时提供的容量小于长度,会panic)
python的列表,其实是个指针数组。当然在下层也会提供一些空位之类的,但基本就是个数组。对它们切片,会创建新的数组,注意,是创建新的数组!python的列表可没有容量的概念。
这其实也体现了脚本语言和编译语言的不同。虽然两个语言都有类似的切片操作;但是python主要目标是方便;go主要目标却是快速(并弥补丢弃指针运算的缺陷)。