Go语言切片详解

article/2025/10/28 23:42:04

切片(slice)是对数组的一个连续片段的引用,所以切片是一个引用类型(因此更类似于 C/C++ 中的数组类型,或者 Python 中的 list 类型),这个片段可以是整个数组,也可以是由起始和终止索引标识的一些项的子集,需要注意的是,终止索引标识的项不包括在切片内。

Go语言中切片的内部结构包含地址、大小和容量,切片一般用于快速地操作一块数据集合,如果将数据集合比作切糕的话,切片就是你要的“那一块”,切的过程包含从哪里开始(切片的起始位置)及切多大(切片的大小),容量可以理解为装切片的口袋大小,如下图所示。

切片操作[开始 :位置](用刀切)
分配的内存
地址
开始位置
大小
切多大
容量
袋子大小

请添加图片描述

Go语言切片详解

    • 从数组或切片生成新的切片
      • 从指定范围中生成切片
      • 表示原有的切片
      • 重置切片,清空拥有的元素
    • 直接声明新的切片
    • 使用 make() 函数构造切片
    • Go语言append()为切片添加元素
    • Go语言copy():切片复制(切片拷贝)
    • Go语言从切片中删除元素
      • 从开头位置删除
      • 从中间位置删除
      • 从尾部删除
    • Go语言range关键字:循环迭代切片
      • 【示例 1】range 提供了每个元素的副本
      • 【示例 2】使用空白标识符(下划线)来忽略索引值
      • 【示例 3】使用传统的 for 循环对切片进行迭代
    • Go语言多维切片简述

从数组或切片生成新的切片

切片默认指向一段连续内存区域,可以是数组,也可以是切片本身。从连续内存区域生成切片是常见的操作,格式如下:

// slice:表示目标切片对象
// 开始位置:对应目标切片对象的索引
// 结束位置:对应目标切片的结束索引
slice [开始位置 : 结束位置]

从数组生成切片,代码如下:

var a  = [3]int{1, 2, 3}
fmt.Println(a, a[1:2])

其中 a 是一个拥有 3 个整型元素的数组,被初始化为数值 1 到 3,使用 a[1:2] 可以生成一个新的切片,代码运行结果如下:

[1 2 3]  [2]

其中 [2] 就是 a[1:2] 切片操作的结果。

从数组或切片生成新的切片拥有如下特性:

  • 取出的元素数量为:结束位置 - 开始位置;
  • 取出元素不包含结束位置对应的索引,切片最后一个元素使用 slice[len(slice)] 获取;
  • 当缺少开始位置时,表示从连续区域开头到结束位置;
  • 当缺少结束位置时,表示从开始位置到整个连续区域末尾;
  • 两者同时缺少时,与切片本身等效;
  • 两者同时为 0 时,等效于空切片,一般用于切片复位。

根据索引位置取切片 slice 元素值时,取值范围是(0~len(slice)-1),超界会报运行时错误,生成切片时,结束位置可以填写 len(slice) 但不会报错。下面通过实例来熟悉切片的特性:

从指定范围中生成切片

切片有点像C语言里的指针,指针可以做运算,但代价是内存操作越界,切片在指针的基础上增加了大小,约束了切片对应的内存区域,切片使用中无法对切片内部的地址和大小进行手动调整,因此切片比指针更安全、强大。

切片和数组密不可分,如果将数组理解为一栋办公楼,那么切片就是把不同的连续楼层出租给使用者,出租的过程需要选择开始楼层和结束楼层,这个过程就会生成切片,示例代码如下:

// 代码中构建了一个 30 层的高层建筑
// 数组的元素值从 1 到 30,分别代表不同的独立楼层,输出的结果是不同的租售方案
var highRiseBuilding [30]intfor i := 0; i < 30; i++ {highRiseBuilding[i] = i + 1
}// 区间
// 尝试出租一个区间楼层
fmt.Println(highRiseBuilding[10:15])// 中间到尾部的所有元素
// 出租 20 层以上
fmt.Println(highRiseBuilding[20:])// 开头到中间指定位置的所有元素
// 出租 2 层以下,一般是商用铺面
fmt.Println(highRiseBuilding[:2])

代码输出如下:

[11 12 13 14 15]
[21 22 23 24 25 26 27 28 29 30]
[1 2]

表示原有的切片

生成切片的格式中,当开始和结束位置都被忽略时,生成的切片将表示和原切片一致的切片,并且生成的切片与原切片在数据内容上也是一致的,代码如下:

a := []int{1, 2, 3}
fmt.Println(a[:])

a 是一个拥有 3 个元素的切片,将 a 切片使用 a[:] 进行操作后,得到的切片与 a 切片一致,代码输出如下:

[1 2 3]

重置切片,清空拥有的元素

把切片的开始和结束位置都设为 0 时,生成的切片将变空,代码如下:

a := []int{1, 2, 3}
fmt.Println(a[0:0])

代码输出如下:

[]

直接声明新的切片

除了可以从原有的数组或者切片中生成切片外,也可以声明一个新的切片,每一种类型都可以拥有其切片类型,表示多个相同类型元素的连续集合,因此切片类型也可以被声明,切片类型声明格式如下:

// 其中 name 表示切片的变量名
// Type 表示切片对应的元素类型
var name []Type

下面代码展示了切片声明的使用过程:

// 声明字符串切片
// 声明一个字符串切片,切片中拥有多个字符串
var strList []string// 声明整型切片
// 声明一个整型切片,切片中拥有多个整型数值
var numList []int// 声明一个空切片
// 将 numListEmpty 声明为一个整型切片
// 本来会在{}中填充切片的初始化元素,这里没有填充,所以切片是空的,但是此时的 numListEmpty 已经被分配了内存,只是还没有元素
var numListEmpty = []int{}// 输出3个切片
// 切片均没有任何元素,3 个切片输出元素内容均为空
fmt.Println(strList, numList, numListEmpty)// 输出3个切片大小
// 没有对切片进行任何操作,strList 和 numList 没有指向任何数组或者其他切片
fmt.Println(len(strList), len(numList), len(numListEmpty))// 切片判定空的结果
//声明但未使用的切片的默认值是 nil,strList 和 numList 也是 nil,所以和 nil 比较的结果是 true
// numListEmpty 已经被分配到了内存,但没有元素,因此和 nil 比较时是 false
fmt.Println(strList == nil)
fmt.Println(numList == nil)
fmt.Println(numListEmpty == nil)

代码输出结果:

[] [] []
0 0 0
true
true
false

使用 make() 函数构造切片

如果需要动态地创建一个切片,可以使用 make() 内建函数,格式如下:

// 其中 Type 是指切片的元素类型
// size 指的是为这个类型分配多少个元素
// cap 为预分配的元素数量,这个值设定后不影响 size,只是能提前分配空间,降低多次分配空间造成的性能问题
make( []Type, size, cap )

示例如下:

a := make([]int, 2)
b := make([]int, 2, 10)fmt.Println(a, b)
fmt.Println(len(a), len(b))

代码输出如下:

[0 0] [0 0]
2 2

其中 a 和 b 均是预分配 2 个元素的切片,只是 b 的内部存储空间已经分配了 10 个,但实际使用了 2 个元素。容量不会影响当前的元素个数,因此 a 和 b 取 len 都是 2。

温馨提示:使用 make() 函数生成的切片一定发生了内存分配操作,但给定开始与结束位置(包括切片复位)的切片只是将新的切片结构指向已经分配好的内存区域,设定开始与结束位置,不会发生内存分配操作。

Go语言append()为切片添加元素

Go语言的内建函数 append() 可以为切片动态添加元素,代码如下所示:

var a []int
a = append(a, 1) // 追加1个元素
a = append(a, 1, 2, 3) // 追加多个元素, 手写解包方式
a = append(a, []int{1,2,3}...) // 追加一个切片, 切片需要解包

不过需要注意的是,在使用 append() 函数为切片动态添加元素时,如果空间不足以容纳足够多的元素,切片就会进行“扩容”,此时新切片的长度会发生改变。切片在扩容时,容量的扩展规律是按容量的 2 倍数进行扩充,例如 1、2、4、8、16……,代码如下:

// 声明一个整型切片
var numbers []int// 循环向 numbers 切片中添加 10 个数
for i := 0; i < 10; i++ {numbers = append(numbers, i)// 打印输出切片的长度、容量和指针变化,使用函数 len() 查看切片拥有的元素个数,使用函数 cap() 查看切片的容量情况fmt.Printf("len: %d  cap: %d pointer: %p\n", len(numbers), cap(numbers), numbers)
}

代码输出如下:

len: 1  cap: 1 pointer: 0xc0420080e8
len: 2  cap: 2 pointer: 0xc042008150
len: 3  cap: 4 pointer: 0xc04200e320
len: 4  cap: 4 pointer: 0xc04200e320
len: 5  cap: 8 pointer: 0xc04200c200
len: 6  cap: 8 pointer: 0xc04200c200
len: 7  cap: 8 pointer: 0xc04200c200
len: 8  cap: 8 pointer: 0xc04200c200
len: 9  cap: 16 pointer: 0xc042074000
len: 10  cap: 16 pointer: 0xc042074000

通过查看代码输出,可以发现一个有意思的规律:切片长度 len 并不等于切片的容量 cap。往一个切片中不断添加元素的过程,类似于公司搬家,公司发展初期,资金紧张,人员很少,所以只需要很小的房间即可容纳所有的员工,随着业务的拓展和收入的增加就需要扩充工位,但是办公地的大小是固定的,无法改变,因此公司只能选择搬家,每次搬家就需要将所有的人员转移到新的办公点。

  • 员工和工位就是切片中的元素。
  • 办公地就是分配好的内存。
  • 搬家就是重新分配内存。
  • 无论搬多少次家,公司名称始终不会变,代表外部使用切片的变量名不会修改。
  • 由于搬家后地址发生变化,因此内存“地址”也会有修改。

除了在切片的尾部追加,我们还可以在切片的开头添加元素:

var a = []int{1,2,3}
a = append([]int{0}, a...) // 在开头添加1个元素
a = append([]int{-3,-2,-1}, a...) // 在开头添加1个切片

在切片开头添加元素一般都会导致内存的重新分配,而且会导致已有元素全部被复制 1 次,因此,从切片的开头添加元素的性能要比从尾部追加元素的性能差很多。

因为 append 函数返回新切片的特性,所以切片也支持链式操作,我们可以将多个 append 操作组合起来,实现在切片中间插入元素:

var a []int
a = append(a[:i], append([]int{x}, a[i:]...)...) // 在第i个位置插入x
a = append(a[:i], append([]int{1,2,3}, a[i:]...)...) // 在第i个位置插入切片

每个添加操作中的第二个 append 调用都会创建一个临时切片,并将 a[i:] 的内容复制到新创建的切片中,然后将临时创建的切片再追加到 a[:i] 中。

Go语言copy():切片复制(切片拷贝)

Go语言的内置函数 copy() 可以将一个数组切片复制到另一个数组切片中,如果加入的两个数组切片不一样大,就会按照其中较小的那个数组切片的元素个数进行复制。copy() 函数的使用格式如下:

// 其中 srcSlice 为数据来源切片
// destSlice 为复制的目标(也就是将 srcSlice 复制到 destSlice)
// 目标切片必须分配过空间且足够承载复制的元素个数,并且来源和目标的类型必须一致
// copy() 函数的返回值表示实际发生复制的元素个数。copy( destSlice, srcSlice []T) int

下面的代码展示了使用 copy() 函数将一个切片复制到另一个切片的过程:

slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{5, 4, 3}
copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中
copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置

虽然通过循环复制切片元素更直接,不过内置的 copy() 函数使用起来更加方便,copy() 函数的第一个参数是要复制的目标 slice,第二个参数是源 slice,两个 slice 可以共享同一个底层数组,甚至有重叠也没有问题。下面通过代码演示对切片的引用和复制操作后对切片元素的影响:

package mainimport "fmt"func main() {// 设置元素数量为1000const elementCount = 1000// 预分配足够多的元素切片// 预分配拥有 1000 个元素的整型切片,这个切片将作为原始数据srcData := make([]int, elementCount)// 将切片赋值// 将 srcData 填充 0~999 的整型值for i := 0; i < elementCount; i++ {srcData[i] = i}// 引用切片数据// 将 refData 引用 srcData,切片不会因为等号操作进行元素的复制refData := srcData// 预分配足够多的元素切片// 预分配与 srcData 等大(大小相等)、同类型的切片 copyDatacopyData := make([]int, elementCount)// 将数据复制到新的切片空间中// 使用 copy() 函数将原始数据复制到 copyData 切片空间中copy(copyData, srcData)// 修改原始数据的第一个元素// 修改原始数据的第一个元素为 999srcData[0] = 999// 打印引用切片的第一个元素// 引用数据的第一个元素将会发生变化fmt.Println(refData[0])// 打印复制切片的第一个和最后一个元素// 打印复制数据的首位数据,由于数据是复制的,因此不会发生变化fmt.Println(copyData[0], copyData[elementCount-1])// 复制原始数据从4到6(不包含)// 将 srcData 的局部数据复制到 copyData 中copy(copyData, srcData[4:6])// 打印复制局部数据后的 copyData 元素for i := 0; i < 5; i++ {fmt.Printf("%d ", copyData[i])}
}

Go语言从切片中删除元素

Go语言并没有对删除切片元素提供专用的语法或者接口,需要使用切片本身的特性来删除元素,根据要删除元素的位置有三种情况,分别是从开头位置删除、从中间位置删除和从尾部删除,其中删除切片尾部的元素速度最快。

从开头位置删除

删除开头的元素可以直接移动数据指针:

a = []int{1, 2, 3}
a = a[1:] // 删除开头1个元素
a = a[N:] // 删除开头N个元素

也可以不移动数据指针,但是将后面的数据向开头移动,可以用 append 原地完成(所谓原地完成是指在原有的切片数据对应的内存区间内完成,不会导致内存空间结构的变化):

a = []int{1, 2, 3}
a = append(a[:0], a[1:]...) // 删除开头1个元素
a = append(a[:0], a[N:]...) // 删除开头N个元素

还可以用 copy() 函数来删除开头的元素:

a = []int{1, 2, 3}
a = a[:copy(a, a[1:])] // 删除开头1个元素
a = a[:copy(a, a[N:])] // 删除开头N个元素

从中间位置删除

对于删除中间的元素,需要对剩余的元素进行一次整体挪动,同样可以用 append 或 copy 原地完成:

a = []int{1, 2, 3, ...}
a = append(a[:i], a[i+1:]...) // 删除中间1个元素
a = append(a[:i], a[i+N:]...) // 删除中间N个元素
a = a[:i+copy(a[i:], a[i+1:])] // 删除中间1个元素
a = a[:i+copy(a[i:], a[i+N:])] // 删除中间N个元素

从尾部删除

a = []int{1, 2, 3}
a = a[:len(a)-1] // 删除尾部1个元素
a = a[:len(a)-N] // 删除尾部N个元素

删除开头的元素和删除尾部的元素都可以认为是删除中间元素操作的特殊情况,下面来看一个示例:删除切片指定位置的元素,

package mainimport "fmt"func main() {// 声明一个整型切片,保存含有从 a 到 e 的字符串seq := []string{"a", "b", "c", "d", "e"}// 指定删除位置// 为了演示和讲解方便,使用 index 变量保存需要删除的元素位置index := 2// 查看删除位置之前的元素和之后的元素// seq[:index] 表示的就是被删除元素的前半部分,值为 [1 2]// seq[index+1:] 表示的是被删除元素的后半部分,值为 [4 5]fmt.Println(seq[:index], seq[index+1:])// 将删除点前后的元素连接起来// 使用 append() 函数将两个切片连接起来seq = append(seq[:index], seq[index+1:]...)// 输出连接好的新切片,此时,索引为 2 的元素已经被删除fmt.Println(seq)
}

代码输出结果:

[a b] [d e]
[a b d e]

代码的删除过程可以使用下图来描述。
请添加图片描述
提示:连续容器的元素删除无论在任何语言中,都要将删除点前后的元素移动到新的位置,随着元素的增加,这个过程将会变得极为耗时,因此,当业务需要大量、频繁地从一个切片中删除元素时,如果对性能要求较高的话,就需要考虑更换其他的容器了(如双链表等能快速从删除点删除元素)。

Go语言range关键字:循环迭代切片

通过前面的学习我们了解到切片其实就是多个相同类型元素的连续集合,既然切片是一个集合,那么我们就可以迭代其中的元素,Go语言有个特殊的关键字 range,它可以配合关键字 for 来迭代切片里的每一个元素,如下所示:

// 创建一个整型切片,并赋值
slice := []int{10, 20, 30, 40}
// 迭代每一个元素,并显示其值
// index 和 value 分别用来接收 range 关键字返回的切片中每个元素的索引和值
// 这里的 index 和 value 不是固定的,读者也可以定义成其它的名字
for index, value := range slice {fmt.Printf("Index: %d Value: %d\n", index, value)
}

上面代码的输出结果为:

Index: 0 Value: 10
Index: 1 Value: 20
Index: 2 Value: 30
Index: 3 Value: 40

当迭代切片时,关键字 range 会返回两个值,第一个值是当前迭代到的索引位置,第二个值是该位置对应元素值的一份副本,如下图所示:

请添加图片描述需要强调的是,range 返回的是每个元素的副本,而不是直接返回对该元素的引用,如下所示:

【示例 1】range 提供了每个元素的副本

// 创建一个整型切片,并赋值
slice := []int{10, 20, 30, 40}
// 迭代每个元素,并显示值和地址
for index, value := range slice {fmt.Printf("Value: %d Value-Addr: %X ElemAddr: %X\n", value, &value, &slice[index])
}

输出结果为:

Value: 10 Value-Addr: 10500168 ElemAddr: 1052E100
Value: 20 Value-Addr: 10500168 ElemAddr: 1052E104
Value: 30 Value-Addr: 10500168 ElemAddr: 1052E108
Value: 40 Value-Addr: 10500168 ElemAddr: 1052E10C

因为迭代返回的变量是一个在迭代过程中根据切片依次赋值的新变量,所以 value 的地址总是相同的,要想获取每个元素的地址,需要使用切片变量和索引值(例如上面代码中的 &slice[index])。

如果不需要索引值,也可以使用下划线_来忽略这个值,代码如下所示:

// 创建一个整型切片,并赋值
slice := []int{10, 20, 30, 40}
// 迭代每个元素,并显示其值
for _, value := range slice {fmt.Printf("Value: %d\n", value)
}

【示例 2】使用空白标识符(下划线)来忽略索引值

// 创建一个整型切片,并赋值
slice := []int{10, 20, 30, 40}
// 迭代每个元素,并显示其值
for _, value := range slice {fmt.Printf("Value: %d\n", value)
}

输出结果为:

Value: 10
Value: 20
Value: 30
Value: 40

关键字 range 总是会从切片头部开始迭代。如果想对迭代做更多的控制,则可以使用传统的 for 循环,代码如下所示。:

【示例 3】使用传统的 for 循环对切片进行迭代

// 创建一个整型切片,并赋值
slice := []int{10, 20, 30, 40}
// 从第三个元素开始迭代每个元素
for index := 2; index < len(slice); index++ {fmt.Printf("Index: %d Value: %d\n", index, slice[index])
}

输出结果为:

Index: 2 Value: 30
Index: 3 Value: 40

在前面的学习中我们了解了两个特殊的内置函数 len() 和 cap(),可以用于处理数组、切片和通道,对于切片,函数 len() 可以返回切片的长度,函数 cap() 可以返回切片的容量,在上面的示例中,使用到了函数 len() 来控制循环迭代的次数。

当然,range 关键字不仅仅可以用来遍历切片,它还可以用来遍历数组、字符串、map 或者通道等。

Go语言多维切片简述

Go语言中同样允许使用多维切片,声明一个多维数组的语法格式如下:

// sliceName 为切片的名字
// sliceType为切片的类型
// 每个[ ]代表着一个维度,切片有几个维度就需要几个[ ]
var sliceName [][]...[]sliceType

下面以二维切片为例,声明一个二维切片并赋值,代码如下所示:

//声明一个二维切片
var slice [][]int
//为二维切片赋值
slice = [][]int{{10}, {100, 200}}

上面的代码也可以简写为下面的样子:

// 声明一个二维整型切片并赋值
slice := [][]int{{10}, {100, 200}}

上面的代码中展示了一个包含两个元素的外层切片,同时每个元素包又含一个内层的整型切片,切片 slice 的值如下图所示:
请添加图片描述
通过上图可以看到外层的切片包括两个元素,每个元素都是一个切片,第一个元素中的切片使用单个整数 10 来初始化,第二个元素中的切片包括两个整数,即 100 和 200。

这种组合可以让用户创建非常复杂且强大的数据结构,前面介绍过的关于内置函数 append() 的规则也可以应用到组合后的切片上,如下所示:
【示例】组合切片的切片 :

// 声明一个二维整型切片并赋值
slice := [][]int{{10}, {100, 200}}
// 为第一个切片追加值为 20 的元素
slice[0] = append(slice[0], 20)

Go语言里使用 append() 函数处理追加的方式很简明,先增长切片,再将新的整型切片赋值给外层切片的第一个元素,当上面代码中的操作完成后,再将切片复制到外层切片的索引为 0 的元素,如下图所示:
请添加图片描述
即便是这么简单的多维切片,操作时也会涉及众多的布局和值,在函数间这样传递数据结构会很复杂,不过切片本身结构很简单,可以用很小的成本在函数间传递。


http://chatgpt.dhexx.cn/article/Ze5U4970.shtml

相关文章

字符串的切片1

切片的基本语法格式&#xff1a;[头下标&#xff1a;尾下标&#xff1a;步长] 1.字符串切片可以对字符串进行截取操作&#xff0c;获取一段子串。 2.[头下标&#xff1a;尾下标]遵循前闭后开规则&#xff08;头标可取到&#xff0c;尾标取不到&#xff09;。 3.步长可省略&a…

Python3的切片

Python3的切片非常灵活&#xff0c;可以很方便地对有序序列进行切片操作&#xff0c;代码简单易用。 大家都知道&#xff0c;我们可以直接使用索引来访问序列中的元素&#xff0c;同时索引可分为正向和负向两种&#xff0c;而切片也会用到索引&#xff0c;下面放上一个图&…

Python列表切片详解([][:][::])

Python切片是list的一项基本的功能&#xff0c;最近看到了一个程序&#xff0c;里面有这样一句类似的代码&#xff1a; a list[::10] 不太明白两个冒号的意思就上网百度&#xff0c;发现大多数人写的博客中都没有提到这一个用法&#xff0c;因此自己翻阅《Python核心编程中文…

Numpy 数组切片

一、列表切片&#xff08;一维数组&#xff09; 1.1、切片原理 列表切片是从原始列表中提取列表的一部分的过程。在列表切片中&#xff0c;我们将根据所需内容&#xff08;如&#xff0c;从何处开始&#xff0c;结束以及增量进行切片&#xff09;剪切列表。Python中符合序列的…

python 字符串切片

1. 字符串的索引 字符串的索引从前往后是从0开始计数&#xff0c;从后往前是从-1开始依次 -1 2.字符串切片方法 语法格式 str[beginIndex:endIndex:step]取值结果: [begin,end) / 含头不含尾 步长不设置时默认为1 3.切片 ① 取x-y位置的字符串: 从中间开始&#xff0c;中间…

Python 列表切片操作

Python列表切片 切片是Python序列的重要操作之一&#xff0c;适用于列表、元组、字符串、range对象等。可以用切片截取列表中任何部分来获得一个新的列表&#xff0c;也可以进行元素的增、删、改。在Python中&#xff0c;序列的序号即可以从左向右以0开始依次增加&#xff0c;…

Python 列表切片详解

一、列表切片 切指–将某些东西切成小块。列表切片是从原始列表中提取列表的一部分的过程。在列表切片中&#xff0c;我们将根据所需内容&#xff08;如&#xff0c;从何处开始&#xff0c;结束以及增量进行切片&#xff09;剪切列表。 Python中符合序列的有序序列都支持切片&a…

详解Python中的切片(一看就懂版)

前言 在我们使用Python的时候&#xff0c;经常会听到“切片”这个词&#xff01;那什么是切片呢&#xff1f;切片是对序列数据&#xff08;列表、元组、字符串&#xff09;&#xff0c;根据下标索引&#xff0c;对一定范围内数据的获取。 简单来说就是&#xff0c;通过下标索引…

图片切片分割

在处理图片时&#xff0c;若加载一个大的图像&#xff0c;它加载所需要的时间一般会很长。 普通解决办法&#xff1a;压缩图片。 压缩时需要注意以下几个问题&#xff1a; 1、实际文件的大小; 2、分辨率; 3、压缩&#xff1b; 一般来说&#xff0c;压缩图片会使图像质量受…

python中[-1] [:-1] [::-1] [n::-1] 切片的用法

首先简明概要说明用法&#xff0c;然后再用实际例子阐述。 用法概述 [-1] [:-1] [::-1] [n::-1]都是python中切片的使用方法。 [-1]&#xff1a;获取最后一个元素&#xff0c;类似于matlab中的end&#xff1b;[:-1]&#xff1a;除了最后一个元素&#xff0c;获取其他所有的元…

第五节——切片

切片 切片&#xff08;Slice&#xff09;是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活&#xff0c;支持自动扩容。切片是一个引用类型&#xff0c;它的内部结构包含地址、长度和容量。切片一般用于快速地操作一块数据集合。 切片定义 …

切片(slice)

一.切片的基本介绍(slice) (1) 切片是一个数组的引用&#xff0c;因此切片是引用类型&#xff0c;在进行传递时&#xff0c;遵守引用传递的机制。 (2) 切片的使用和数组类似&#xff0c;遍历切片、访问切片的元素和求切片长度len(slice)都一样 (3)切片的长度是可以变化的&#…

切片基础知识

一、切片含义 1.切片(slice)是对序列型对象的一种高级索引方法。python中是用来切割可迭代对象&#xff08;容器&#xff09; 2.切片对象&#xff1a;列表list, 字符串string, 元组tuple&#xff0c;range函数等 二、形式 一个完整的切片有三个参数 object[start:end:step…

Python中的切片(详细篇)学起来喔

Python中的切片知识. 在Python中&#xff0c;切片(slice)是对序列型对象(如list, string, tuple)的一种高级索引方法。 普通索引只取出序列中 一个下标 对应的元素&#xff0c;而切片取出序列中 一个范围 对应的元素&#xff0c;这里的范围不是狭义上的连续片段。通俗一点就是…

Python基础知识:切片

什么是切片操作 在Python中&#xff0c;切片(slice)是对序列型对象(如list, string, tuple)的一种高级索引方法。普通索引只取出序列中一个下标对应的元素&#xff0c;而切片取出序列中一个范围对应的元素&#xff0c;这里的范围不是狭义上的连续片段。下面的代码初步展示了切…

Django 对接 Mysql Datatime 日期格式化处理

查询显示结果时&#xff0c;前端界面会是英文格式显示日期&#xff0c;那么应该怎么处理&#xff1f; 这里直接在前端操作&#xff0c;将日期格式化 “ | ” 符号后&#xff0c;拼接日期格式根据本身数据库显示格式来去&#xff0c;我这里是年月日&#xff0c;时分秒

MySQL 日期类型小数秒的处理

一、 MySQL 日期类型对小数秒的支持 注&#xff1a;本文所使用MySQL版本为 5.7 版本。 官方文档&#xff1a;https://dev.mysql.com/doc/refman/5.7/en/fractional-seconds.html 1、小数秒位数精度 MySQL 支持小数秒的展示&#xff0c;比如官网的例子&#xff0c;在建表时&…

Java 接收 MySQL datetime 类型日期字段输出格式问题

文章目录 前言Java 与 MySQL 类型对应注解操作代码格式转换参考 前言 不管世事多艰难&#xff0c;别忘了&#xff0c;看开点儿&#xff0c;再温柔点儿&#xff0c;不要满身戾气&#xff0c;也不要紧皱眉头&#xff0c;生活都是在你眉开眼笑的时候&#xff0c;一天天好起来的。…

mysql查询数据库日期_mysql如何查询日期与时间

前言: 在项目开发中,一些业务表字段经常使用日期和时间类型,而且后续还会牵涉到这类字段的查询。关于日期及时间的查询等各类需求也很多,本篇文章简单讲讲日期及时间字段的规范化查询方法。 1.日期和时间类型概览 MySQL支持的日期和时间类型有 DATETIME、TIMESTAMP、DATE、…

操作MYSQL日期格式年 或 月 或 日

1&#xff0c;年(year)&#xff1a; select year(create_time) from person2&#xff0c;月(month)&#xff1a; select month(create_time) from person3&#xff0c;日&#xff08;day&#xff09;&#xff1a; select day(create_time) from person4&#xff0c;yyyy-MM-…