浅析深拷贝和浅拷贝(python和go的切片)
发布人:shili8
发布时间:2024-12-23 19:27
阅读次数:0
**浅析深拷贝和浅拷贝**
在编程中,数据结构的复制是非常重要的一环。我们经常会遇到需要复制一个对象或集合的场景,但问题是,我们应该使用浅拷贝还是深拷贝呢?本文将浅析这两个概念,并提供 Python 和 Go语言中的切片(slice)作为示例。
**浅拷贝**
浅拷贝是一种只复制对象或集合的引用,而不是实际的值。也就是说,新创建的对象或集合是原来的对象或集合的一个副本,但它们共享相同的内存空间。这意味着如果原始对象或集合发生变化,副本也会随之改变。
**Python 中的浅拷贝**
在 Python 中,可以使用 `copy` 模块中的 `copy()` 函数来实现浅拷贝。例如:
import copyoriginal_list = [1,2,3] shallow_copied_list = copy.copy(original_list) print(id(original_list)) # 输出:140737354176528print(id(shallow_copied_list)) # 输出:140737354176528# 修改原始列表original_list.append(4) print(original_list) # 输出: [1,2,3,4] print(shallow_copied_list) # 输出: [1,2,3] # 修改浅拷贝的列表shallow_copied_list.append(5) print(original_list) # 输出: [1,2,3,4] print(shallow_copied_list) # 输出: [1,2,3,5]
如上所示,浅拷贝的列表虽然是原始列表的一个副本,但它们共享相同的内存空间。因此,当修改原始列表或浅拷贝的列表时,都会影响到另一个。
**Go 中的切片**
在 Go语言中,切片(slice)是一种引用类型,它指向一个底层数组。也就是说,切片本身并不包含任何数据,而是指向一个底层数组中的某个部分。
gopackage mainimport "fmt" func main() { originalSlice := []int{1,2,3} shallowCopiedSlice := append([]int{}, originalSlice...) fmt.Println(originalSlice) // 输出: [123] fmt.Println(shallowCopiedSlice) // 输出: [123] // 修改原始切片 originalSlice = append(originalSlice,4) fmt.Println(originalSlice) // 输出: [1234] fmt.Println(shallowCopiedSlice) // 输出: [123] // 修改浅拷贝的切片 shallowCopiedSlice = append(shallowCopiedSlice,5) fmt.Println(originalSlice) // 输出: [1234] fmt.Println(shallowCopiedSlice) // 输出: [1235] }
如上所示,Go 中的切片也是通过浅拷贝实现的。因此,当修改原始切片或浅拷贝的切片时,都会影响到另一个。
**深拷贝**
深拷贝是一种复制对象或集合的实际值,而不是引用。这意味着新创建的对象或集合是原来的对象或集合的一个完全独立的副本,它们不共享相同的内存空间。因此,如果原始对象或集合发生变化,副本不会受到影响。
**Python 中的深拷贝**
在 Python 中,可以使用 `copy` 模块中的 `deepcopy()` 函数来实现深拷贝。例如:
import copyoriginal_list = [1,2,3] deep_copied_list = copy.deepcopy(original_list) print(id(original_list)) # 输出:140737354176528print(id(deep_copied_list)) # 输出:140737354177024# 修改原始列表original_list.append(4) print(original_list) # 输出: [1,2,3,4] print(deep_copied_list) # 输出: [1,2,3] # 修改深拷贝的列表deep_copied_list.append(5) print(original_list) # 输出: [1,2,3,4] print(deep_copied_list) # 输出: [1,2,3,5]
如上所示,深拷贝的列表是原始列表的一个完全独立的副本,它们不共享相同的内存空间。因此,当修改原始列表或深拷贝的列表时,都不会影响到另一个。
**Go 中的切片**
在 Go语言中,切片(slice)是一种引用类型,它指向一个底层数组。也就是说,切片本身并不包含任何数据,而是指向一个底层数组中的某个部分。
gopackage mainimport "fmt" func main() { originalSlice := []int{1,2,3} deepCopiedSlice := make([]int, len(originalSlice)) for i, v := range originalSlice { deepCopiedSlice[i] = v } fmt.Println(originalSlice) // 输出: [123] fmt.Println(deepCopiedSlice) // 输出: [123] // 修改原始切片 originalSlice = append(originalSlice,4) fmt.Println(originalSlice) // 输出: [1234] fmt.Println(deepCopiedSlice) // 输出: [123] // 修改深拷贝的切片 deepCopiedSlice = append(deepCopiedSlice,5) fmt.Println(originalSlice) // 输出: [1234] fmt.Println(deepCopiedSlice) // 输出: [1235] }
如上所示,Go 中的切片也是通过深拷贝实现的。因此,当修改原始切片或深拷贝的切片时,都不会影响到另一个。
**结论**
在本文中,我们浅析了浅拷贝和深拷贝两个概念,并提供了 Python 和 Go语言中的切片(slice)作为示例。通过这些例子,我们可以看出,浅拷贝和深拷贝的区别在于它们是否共享相同的内存空间。如果是浅拷贝,则新创建的对象或集合会共享原始对象或集合的内存空间;如果是深拷贝,则新创建的对象或集合是一个完全独立的副本,不共享原始对象或集合的内存空间。