一日一技:Golang 字符串切片与 Python 列表的不同

简介: 一日一技:Golang 字符串切片与 Python 列表的不同

今天我们来看一个非常基础的数据结构:Python中的列表和 Golang 中的切片(Slice)


这两个数据结构从形式上来说,非常相似。我们今天来对比一个只包含字符串的列表和一个字符串切片。


相同点


在 Python 里面,我们定义一个有初始值的字符串列表:


a = ['kingname', 'pm', 'xxx']


在 Golang 里面,我们定义一个有初始值的字符串切片:


a := []string{"kingname", "pm", "xxx"}


接下来,我们分别往字符串列表和字符串切片末尾增加几个元素:


a.append("address")
a.append("shanghai")


在 Golang 里面:


a = append(a, "address")
a = append(a, "shanghai")


我们也可以赋值给其他的变量,看看修改一个,另一个是否会发生修改:


b = a
a[0] = 'superman'
print(b)


运行效果如下图所示:


1.png


我们再来看看在 Golang 的效果:


b := a
a[0] = "superman"
fmt.Println(b)


运行效果如下图所示:


2.png


那么,我们是不是可以说,Golang 的切片就相当于 Python 里面元素数据类型相同的列表?


不同点


现在,我们再往列表和字符串切片里面各加一个元素,来看看运行效果:

在 Python 里面,运行效果如下图所示:


3.png


进一步实验你会发现,a 和 b 两个列表是完全一样的,只要修改任何一个列表,另一个都会随之发生变化。


但是 Golang 里面并不是这样,如下图所示:


4.png


你修改任何一个切片,另一个切片都不会改变。


看到这里,你可能会觉得 Golang 里面,是不是append添加新的数据,每次都会生成新的切片,所以才导致添加数据以后两个切片就不一样了。


但实际上并不是这样,我们用另外一种初始化切片的方式来做一个测试:


5.png


在这个例子里面,我生成了一个长度为5,容量为20的字符串切片。根据第15-19行的运行结果可以看到,此时,无论是根据索引修改里面的元素,还是使用 append 添加新的元素,两个切片的变化都相同。如果我们把切片的容量调小,调整到6,再看看效果:


6.png


从这里可以看到,b 跟着 a 变了半截。a 新增的test字符串同时也能在 b 里面找到。但是 a里面新增的abcde却没有出现在 b 中。并且对a[0]的修改,也没有出现在 b 中。


原因


Golang 的切片之所以会出现这个现象,这需要从数组与切片的区别来说起。在 Golang 里面,字符串数组字符串切片非常像,但他们有一个根本的区别,就是数组是需要一开始就声明长度的,并且不能扩容。而切片不需要声明长度,所以:


[5]string{"xx", "yy"}  // 这是长度为5的字符串数组
[]string{"xx", "yy"} // 字符串切片


而切片底层依然是数组,切片有一个容量的概念,指的就是它底层的数组的长度。如果切片中的数据数量等于了切片的容量,那么下一次再添加一个新的数据的时候,切片底层就会创建一个原来长度2倍(数据量小于1024的时候是2倍,大于1024的时候是1.25倍)的数组,然后把已有数据按顺序拷贝进去,接着再插入新的数据。


所以,回到上面的代码。当我们使用a := make([]string, 5, 6)创建一个容量为6的字符串切片的时候,它底层会初始化一个长度为6的字符串数组。当代码执行到b := a[0: 6]的时候,虽然这里的 b 是另外一个切片,它跟 a 拥有不同的内存地址,但他们共用了同一个底层数组。只要数据小于6,那么对其中一个切片的数据进行修改,本质上就是对它底层数组的修改,而另一个切片也使用这个数组,所以也能看到这个修改。


但是当a数据容量超过6以后,a 切片底层会重新生成一个长度为12的数组,并把原有的老数据都拷贝到新的数组里面,接下来的所有修改都是对这个新的数组进行修改。而此时 b 切片底层还是老的长度为6的数组,所以此时对 a 切片的修改就不会反映到 b 上面了。


请关注微信公众号【未闻Code】获取更多精彩文章。

目录
相关文章
|
2月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
209 1
|
2月前
|
Java 数据处理 索引
(numpy)Python做数据处理必备框架!(二):ndarray切片的使用与运算;常见的ndarray函数:平方根、正余弦、自然对数、指数、幂等运算;统计函数:方差、均值、极差;比较函数...
ndarray切片 索引从0开始 索引/切片类型 描述/用法 基本索引 通过整数索引直接访问元素。 行/列切片 使用冒号:切片语法选择行或列的子集 连续切片 从起始索引到结束索引按步长切片 使用slice函数 通过slice(start,stop,strp)定义切片规则 布尔索引 通过布尔条件筛选满足条件的元素。支持逻辑运算符 &、|。
188 0
|
2月前
|
开发者 Python
Python列表推导式:优雅与效率的完美结合
Python列表推导式:优雅与效率的完美结合
415 116
|
2月前
|
Python
Python列表推导式:简洁与高效的艺术
Python列表推导式:简洁与高效的艺术
451 119
|
2月前
|
Python
Python列表推导式:优雅与效率的艺术
Python列表推导式:优雅与效率的艺术
296 99
|
2月前
|
数据处理 Python
解锁Python列表推导式:优雅与效率的完美融合
解锁Python列表推导式:优雅与效率的完美融合
276 99
|
2月前
|
Python
Python列表推导式:简洁与高效的艺术
Python列表推导式:简洁与高效的艺术
|
2月前
|
索引 Python
Python 列表切片赋值教程:掌握 “移花接木” 式列表修改技巧
本文通过生动的“嫁接”比喻,讲解Python列表切片赋值操作。切片可修改原列表内容,实现头部、尾部或中间元素替换,支持不等长赋值,灵活实现列表结构更新。
133 1
|
2月前
|
大数据 开发者 Python
Python列表推导式:简洁与高效的艺术
Python列表推导式:简洁与高效的艺术
|
2月前
|
存储 Java 索引
(Python基础)新时代语言!一起学习Python吧!(二):字符编码由来;Python字符串、字符串格式化;list集合和tuple元组区别
字符编码 我们要清楚,计算机最开始的表达都是由二进制而来 我们要想通过二进制来表示我们熟知的字符看看以下的变化 例如: 1 的二进制编码为 0000 0001 我们通过A这个字符,让其在计算机内部存储(现如今,A 字符在地址通常表示为65) 现在拿A举例: 在计算机内部 A字符,它本身表示为 65这个数,在计算机底层会转为二进制码 也意味着A字符在底层表示为 1000001 通过这样的字符表示进行转换,逐步发展为拥有127个字符的编码存储到计算机中,这个编码表也被称为ASCII编码。 但随时代变迁,ASCII编码逐渐暴露短板,全球有上百种语言,光是ASCII编码并不能够满足需求
182 4

热门文章

最新文章