python中的可变与不可变、深拷贝和浅拷贝

news2025/2/2 23:49:25

个人猜想(很遗憾失败了)

在硬盘或者系统中存在一个字符集

如果存在硬盘中,那么硬盘出厂的时候他的字符集所占用的空间就已经确定了。

如果存在于系统的话,硬盘应该在出厂的时候为系统设置一个存储系统字符集的地方。在安装系统的时候,把这个字符集放入约定的内存空间中。

当然,这个字符集不管是存在硬盘还是系统自带,硬盘中的这片内存区域是不允许改变的。所以不可变类型的原因就找到了。

文心一言告诉我,确实存在一个字符集,但并不存在于硬盘中,而是存在系统中,用于处理数据

不过可以确定的是,这些不可变数据的创建及存储是有一定规律的

测试一下

使用python输出不可变类型的内存地址

结论:
经过多次运行,这个内存地址在一个时间段内输出的内容是相同的
应该是某种机制在保护,程序结束后并不释放内存空间
而是等待一段时间的下次调用,用来节省资源的消耗

但是结果的差值都为32

a=1
b=2
print("a=",id(a))
print("b=",id(b))

"""
a= 140731726750504
b= 140731726750536

"""

"""
a= 140731562451752
b= 140731562451784
"""

使用 C语言输出不可变类型的内存地址

测试了一下C语言的,发他的内存地址是固定不会变化的

于是我想起来C语言编译型语言,于是又重新创建了一个代码相同的文件,结果竟然是相同的

#include <stdio.h>  
  
int main() {  
    int a = 1;  
    int b = 2;  
  
    printf("变量a的内存地址是:%d\n", &a);  
    printf("变量b的内存地址是:%d\n", &b);  
  
    return 0;  
}

//变量a的内存地址是:6422300
//变量b的内存地址是:6422296

尝试使用虚拟机的ubuntn系统下运行

python测试

结果显示差值为168,但是不会在一段时间内改变

a=1
b=2
print("a=",id(a))
print("b=",id(b))


"""
a= 10894368
b= 10894400
"""

C语言测试

发现每一次的结果都不同,但是每次都相差4,由此想到了系统架构是64还是32,一时间大量的疑问涌入脑中,好吧,时间有限,停止思考,疑问封存

什么是可变与不可变

可变不可变,是指内存中的那块内容(value)是否可以被改变

  • 可变类型(mutable),创建后可以继续修改对象的内容(值)

    字典、列表

  • 不可变类型(unmutable) ,一旦创建就不可修改的对象(值)

    数字, 字符串,元组

什么是深拷贝和浅拷贝

 python中的copy 模块,可以实现拷贝功能

浅拷贝(就像快捷方式)

浅拷贝:引用(地址)拷贝,并没有产生新的空间。如果拷贝的是对象,原对象和copy对象都指向同一个内存空间,只拷贝父对象,不会拷贝对象的内部的子对象

  • 不会产生新的空间
  • 源对象和副本对象指向同一空间
  • 如果拷贝的是对象,子对象不会拷贝(不产生新的空间)

用法: copy.copy(变量) 会进行拷贝

深拷贝(真正的复制)

  • 会产生新的空间
  • 能够保持各自的独立性
  • 如果拷贝的是对象,子对象也会拷贝(产生新的空间)

深拷贝:会产生新的空间。如果拷贝的是对象,原对象和copy对象都指向不同的内存空间,会拷贝对象及其子对象(会产生新的空间)

用法:copy.deepcopy(变量名)

简单可变类型的拷贝

简单可变数据类型不管是深拷贝和浅拷贝,都会产生新的空间,而且保持各自的独立性

验证

浅拷贝

import copy

list1 = [2, 4, 6]
# 浅拷贝
list2 = copy.copy(list1)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
list1.append(8)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
# 测试结果
""""
list1= [2, 4, 6] 2366561172928
list2= [2, 4, 6] 2366558942976
list1= [2, 4, 6, 8] 2366561172928
list2= [2, 4, 6] 2366558942976
"""

深拷贝

import copy

list1=[2,4,6]
# 深拷贝
list2=copy.deepcopy(list1)

print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
list1.append(8)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
# 测试结果
"""
list1= [2, 4, 6] 2447599320576
list2= [2, 4, 6] 2447598755904
list1= [2, 4, 6, 8] 2447599320576
list2= [2, 4, 6] 2447598755904
"""

复杂可变类型的拷贝

复杂类型的内存地址是引用

list1 = [1, 3, 5]
list2 = [2, 4, 6]

list3 = [list1, list2]

print("list1=", list1, id(list1))
print("list2=", list2, id(list2))
print("list3=", list3, id(list3))
print("list3[0]=", list3[0], id(list3[0]))

"""
嵌套只是引用
list1= [1, 3, 5] 2090564943424
list2= [2, 4, 6] 2090564397632
list3= [[1, 3, 5], [2, 4, 6]] 2090562664192
list3[0]= [1, 3, 5] 2090564943424
"""

浅拷贝(对快捷方式创建快捷方式)

  • 复杂可变类型的 浅拷贝,实际上是引用拷贝,无法保持独立性

验证

import copy

list1 = [1, 3, 5]
list2 = [2, 4, 6]

list3 = [list1, list2]

# 已知,复杂类型的内存地址是引用
# 所以对复杂类型进行浅拷贝
list4 = copy.copy(list3)

list1.append(7)
print("list1=", list1, id(list1))
print("list3=", list3, id(list3))
print("list4=", list4, id(list4))
print("list4=[0]", list4[0], id(list4[0]))

"""运行结果:在浅拷贝结束后
对简单类型进行数据的添加
复杂类型的内容会改变,浅拷贝的内容也会发生改变
而浅拷贝的地址改变了
所以浅拷贝针对复杂类型最顶层
list1= [1, 3, 5, 7] 3144178450048
list3= [[1, 3, 5, 7], [2, 4, 6]] 3144178363904
list4= [[1, 3, 5, 7], [2, 4, 6]] 3144178364544
list4=[0] [1, 3, 5, 7] 3144178450048
"""

深拷贝(真正的复制)

  • 复杂可变类型的 深拷贝,此时会产生新的内存空间

验证

import copy

list1 = [1, 3, 5]
list2 = [2, 4, 6]

list3 = [list1, list2]

# 进行深拷贝
list4 = copy.deepcopy(list3)

list1.append(7)
print("list1=", list1, id(list1))
print("list3=", list3, id(list3))
print("list4=", list4, id(list4))
print("list4=[0]", list4[0], id(list4[0]))

"""运行结果:
深拷贝将复杂类型中的简单类型数据也进行了复制
实现了完全复制
list1= [1, 3, 5, 7] 1623394860736
list3= [[1, 3, 5, 7], [2, 4, 6]] 1623394774528
list4= [[1, 3, 5], [2, 4, 6]] 1623394775104
list4=[0] [1, 3, 5] 1623394775360
"""

简单不可变类型的拷贝(都是浅拷贝)

验证

import copy


def copy_popy():
    tuple1=(1,3,5)

    # 浅拷贝
    tuple2=copy.copy(tuple1)

    print("tuple1=",tuple1,id(tuple1))
    print("tuple2=",tuple2,id(tuple2))

    """运行结果:
    tuple1= (1, 3, 5) 2239384263296
    tuple2= (1, 3, 5) 2239384263296
    """


tuple1=(1,3,5)
#深拷贝
tuple2=copy.deepcopy(tuple1)

print("tuple1=",tuple1,id(tuple1))
print("tuple2=",tuple2,id(tuple2))

"""运行结果
tuple1= (1, 3, 5) 2406599105152
tuple2= (1, 3, 5) 2406599105152
"""

复杂不可变类型的拷贝

复杂不可变类型的本质

import copy

list1=[1,3,5]
list2=[2,4,6]

tuple1=(list1,list2)

print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))


"""运行结果
list1= [1, 3, 5] 2175399394816
tuple1= ([1, 3, 5], [2, 4, 6]) 2175399258432
tuple1[0]= [1, 3, 5] 2175399394816
"""

验证

浅拷贝

只关心最外层的数据类型是什么,如果是不可变类型,直接引用,没有办法保证数据的独立性

外层为不可变,内层为可变

import copy

list1=[1,3,5]
list2=[2,4,6]

tuple1=(list1,list2)

# 进行浅拷贝
tuple2=copy.copy(tuple1)

print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2=",tuple2,id(tuple2))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))


"""运行结果
list1= [1, 3, 5] 2384705011392
tuple1= ([1, 3, 5], [2, 4, 6]) 2384704858432
tuple1[0]= [1, 3, 5] 2384705011392


tuple2= ([1, 3, 5], [2, 4, 6]) 2384704858432
tuple2[0]= [1, 3, 5] 2384705011392
"""

外层为可变,内层为不可变
import copy

list1=(1,3,5)
list2=(2,4,6)

tuple1=[list1,list2]

# 进行浅拷贝
tuple2=copy.copy(tuple1)

print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2=",tuple2,id(tuple2))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))


"""运行结果
list1= (1, 3, 5) 2192295467648
tuple1= [(1, 3, 5), (2, 4, 6)] 2192295837376
tuple1[0]= (1, 3, 5) 2192295467648

tuple2= [(1, 3, 5), (2, 4, 6)] 2192295274688
tuple2[0]= (1, 3, 5) 2192295467648
"""

深拷贝

这个数据是否有可变的数据类型,如果有它就会为可变类型开辟多个空间存储数据和地址,达到保证数据独立性的作用

外层为可变类型
import copy

list1=(1,3,5)
list2=(2,4,6)

tuple1=[list1,list2]

# 进行深拷贝
tuple2=copy.deepcopy(tuple1)

print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2=",tuple2,id(tuple2))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))


"""运行结果
list1= (1, 3, 5) 2050110790272
tuple1= [(1, 3, 5), (2, 4, 6)] 2050111160000
tuple1[0]= (1, 3, 5) 2050110790272


tuple2= [(1, 3, 5), (2, 4, 6)] 2050111074560
tuple2[0]= (1, 3, 5) 2050110790272
"""

外层为不可变类型 
import copy

list1 = [1, 3, 5]
list2 = [2, 4, 6]

tuple1 = (list1, list2)

# 进行深拷贝
tuple2 = copy.deepcopy(tuple1)

print("list1=", list1, id(list1))
print("tuple1=", tuple1, id(tuple1))
print("tuple1[0]=", tuple1[0], id(tuple1[0]))
print("tuple2=", tuple2, id(tuple2))
print("tuple2[0]=", tuple2[0], id(tuple2[0]))

"""运行结果
list1= [1, 3, 5] 2221492256448
tuple1= ([1, 3, 5], [2, 4, 6]) 2221492103488
tuple1[0]= [1, 3, 5] 2221492256448

tuple2= ([1, 3, 5], [2, 4, 6]) 2221492102912
tuple2[0]= [1, 3, 5] 2221492170816
"""
内外都不可变
import copy

list1 = (1, 3, 5)
list2 = (2, 4, 6)

tuple1 = (list1, list2)

# 进行深拷贝
tuple2 = copy.deepcopy(tuple1)

print("list1=", list1, id(list1))
print("tuple1=", tuple1, id(tuple1))
print("tuple1[0]=", tuple1[0], id(tuple1[0]))
print("tuple2=", tuple2, id(tuple2))
print("tuple2[0]=", tuple2[0], id(tuple2[0]))

"""运行结果
list1= (1, 3, 5) 2647937981056
tuple1= ((1, 3, 5), (2, 4, 6)) 2647938197824
tuple1[0]= (1, 3, 5) 2647937981056

tuple2= ((1, 3, 5), (2, 4, 6)) 2647938197824
tuple2[0]= (1, 3, 5) 2647937981056
"""

注意:只要是可变类型不管是深拷贝都会开辟新的空间 

切片拷贝(变量名[:])

切片拷贝,是一种浅拷贝,副本对象和原对象指向同一个空间

简单可变类型

list1 = [1, 3, 5]

list2 = list1[:]

print("list1=", list1, id(list1))
print("list2=", list2, id(list2))

list2.append(7)
print("list1=", list1, id(list1))
print("list2=", list2, id(list2))

"""运行结果
list1= [1, 3, 5] 1612210008768
list2= [1, 3, 5] 1612211181632

list1= [1, 3, 5] 1612210008768
list2= [1, 3, 5, 7] 1612211181632
"""

复杂不可变类型

list1 = [1, 3, 5]
list2 = [2, 4, 6]

tuple1=(list1,list2)

tuple2=tuple1[:]

print("list1=",list1,id(list1))
print("tuple1=",tuple1,id(tuple1))
print("tuple2=",tuple2,id(tuple2))
print("tuple1[0]=",tuple1[0],id(tuple1[0]))
print("tuple2[0]=",tuple2[0],id(tuple2[0]))
list1.append(7)
print("tuple2[0]=",tuple2[0],id(tuple2[0]))

"""运行结果得出,切片拷贝是浅拷贝
list1= [1, 3, 5] 2281363043008
tuple1= ([1, 3, 5], [2, 4, 6]) 2281364482816
tuple2= ([1, 3, 5], [2, 4, 6]) 2281364482816

tuple1[0]= [1, 3, 5] 2281363043008
tuple2[0]= [1, 3, 5] 2281363043008
tuple2[0]= [1, 3, 5, 7] 2281363043008
"""

字典拷贝 (字典名.copy())

字典提供一个copy()方法,也是浅拷贝,虽然地址发生改变,但是内部的对象仍然是链接状态

test_dict1={"age":[10,20,30]}

test_dict2=test_dict1.copy()

print("test_dict1=",test_dict1,id(test_dict1))
print("test_dict2=",test_dict2,id(test_dict2))
test_dict1["age"][0]=100

print("test_dict1=",test_dict1,id(test_dict1))
print("test_dict2=",test_dict2,id(test_dict2))

"""运行结果显示,字典拷贝为浅拷贝
test_dict1= {'age': [10, 20, 30]} 2561919905472
test_dict2= {'age': [10, 20, 30]} 2561921341312

test_dict1= {'age': [100, 20, 30]} 2561919905472
test_dict2= {'age': [100, 20, 30]} 2561921341312
"""

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1427649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[蓝桥杯难题总结-Python]乘积最大

乘积最大 题目描述 今年是国际数学联盟确定的“ 2000 ——世界数学年”&#xff0c;又恰逢我国著名数学家华罗庚先生诞辰 90 周年。在华罗庚先生的家乡江苏金坛&#xff0c;组织了一场别开生面的数学智力竞赛的活动&#xff0c;你的一个好朋友 XZ 也有幸得以参加。活动中&…

部署实战--修改jar中的文件并重新打包成jar文件

一.jar文件 JAR 文件就是 Java Archive &#xff08; Java 档案文件&#xff09;&#xff0c;它是 Java 的一种文档格式JAR 文件与 ZIP 文件唯一的区别就是在 JAR 文件的内容中&#xff0c;多出了一个META-INF/MANIFEST.MF 文件META-INF/MANIFEST.MF 文件在生成 JAR 文件的时候…

【jenkins】主从机制及添加Slave节点操作

一、master-slave 日常构建Jenkins任务中&#xff0c;会经常出现下面的情况&#xff1a; 自动化测试需要消耗大量的 CPU 和内存资源&#xff0c;如果服务器上还有其他的服务&#xff0c;可能会造成卡顿或者宕机这样的情况&#xff1b; Jenkins 平台上除了这个项目&#xff0c…

SpringBoot security 安全认证(一)——登录验证

本节内容&#xff1a;使用springboot自动security模块实现用户登录验证功能&#xff1b; 登录过程如下图&#xff1a; AuthenticationManager内容实现用户账号密码验证&#xff0c;还可以对用户状态&#xff08;启用/禁用&#xff09;&#xff0c;逻辑删除&#xff0c;账号是否…

RS485通信在钡铼技术的LoRa网关中的应用

在钡铼技术的LoRa网关中&#xff0c;RS485通信协议的应用是一个典型的示例&#xff0c;展现了如何将传统的工业通信技术与现代的物联网(IoT)解决方案相结合&#xff0c;以实现更加高效、可靠的数据传输和设备管理。RS485作为一种广泛使用的串行通信协议&#xff0c;因其稳定性高…

分类预测 | Matlab实现SCN-Adaboost随机配置网络模型SCN的Adaboost数据分类预测/故障识别

分类预测 | Matlab实现SCN-Adaboost随机配置网络模型SCN的Adaboost数据分类预测/故障识别 目录 分类预测 | Matlab实现SCN-Adaboost随机配置网络模型SCN的Adaboost数据分类预测/故障识别分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现SCN-Adaboost随机配置网…

2024最新!软件测试高频面试题基础知识点分享

近期也算是抽取出大部分休息的时间&#xff0c;为大家准备了一份通往大厂面试的小捷径&#xff0c;准备了一整套软件测试复习面试的刷题以及答案&#xff0c;我知道很多同学不知道怎么复习&#xff0c;不知道学习过程中哪些才是重点&#xff0c;其实&#xff0c;你们经历过的事…

C/C++ 回调函数 callback 异步编程

一、C语言的回调函数 1.小试牛刀 #include <iostream> using namespace std; #include <memory> #include <stdlib.h>int add(int a, int b) {return a b; }void test01() {// 函数指针可以指向任何类型的函数&#xff0c;只要函数的参数列表和返回值类型…

数据结构 归并排序详解

1.基本思想 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide andConquer&#xff09;的一个非常典型的应用。 将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff0c;即先使每个子序列有序…

HAL库配置片内FLASH读写

一、FLASH简介 不同型号的 STM32F40xx/41xx&#xff0c;其 FLASH 容量也有所不同&#xff0c;最小的只有 128K 字节&#xff0c;最大 的则达到了 1024K 字节。我们的探索者开发板选择的是 STM32F407ZGT6 的 FLASH 容量为 1024K 字节。 主存储器&#xff0c;存放代码和数据常数&…

关于ZYZ旋转和XYZ旋转

ZYZ旋转和XYZ旋转 概述1、XYZ旋转2、ZYZ旋转 概述 以下公式默认为右手坐标系&#xff1b;ZYZ通常可以避免死解情况&#xff0c;因此在六轴末端解算时常被用到&#xff1b;参考文章 1、XYZ旋转 XYZ旋转一般是绕固定轴旋转(外旋)&#xff0c;旋转矩阵的构成为&#xff1a;RzRy…

关于如何利用ChatGPT提高编程效率的

自从去年ChatGPT3.5推出以后&#xff0c;这一年时间在编程过程中我也在慢慢熟悉人工智能的使用&#xff0c;目前来看即使是免费的ChatGPT3.5对于编程效率的提升也是有很大帮助的&#xff0c;虽然在使用过程中确实出现了一些问题&#xff0c;本文记录下我的一些心得体会和用法。…

ubuntu安装docker及插件docker-compose(详细图文)

目录 一、摘要 二、说明 三、安装docker及compose 方式一&#xff1a;采用apt存储库安装 1.设置 Docker 的存储库 2.1安装最新Docker包及其常用插件docker-compose 2.2安装指定 Docker 包及其常用插件docker-compose &#xff08;1&#xff09;列出所有存储库中docker版…

Docker中配置MySql环境

目录 一、简单安装 1. 首先从Docker Hub中拉取镜像 2. 启动尝试创建MySQL容器&#xff0c;并设置挂载卷。 3. 查看mysql8这个容器是否启动成功 4. 如果已经成功启动&#xff0c;进入容器中简单测试 4.1 进入容器 4.2 登录mysql中 4.3 进行简单添加查找测试 二、主从复…

Linux实验记录:使用Apache的虚拟主机功能

前言&#xff1a; 本文是一篇关于Linux系统初学者的实验记录。 参考书籍&#xff1a;《Linux就该这么学》 实验环境&#xff1a; VmwareWorkStation 17——虚拟机软件 RedHatEnterpriseLinux[RHEL]8——红帽操作系统 正文&#xff1a; 目录 前言&#xff1a; 正文&…

行业报告 | 工业机器人发展研报

原创 | 文 BFT机器人 工业机器人是一种能够自动执行任务的机器装置&#xff0c;是靠自身动力和控制能力来实现各种功能的一种机器。在工业生产过程中&#xff0c;可以大幅提高生产效率和产品质量。 随着科技的不断进步&#xff0c;工业机器人已经成为现代制造业的重要组成部分…

【Unity3D小技巧】Unity3D中UI控制解决方案

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在开发中总是会控制UI界面&#xff0c;如何优雅的控制UI界面是…

亚马逊精品广告推广怎么做?亚马逊怎么看精品广告推广?站斧浏览器

亚马逊精品广告推广怎么做? 对于想要在亚马逊平台上进行精品广告推广的商家来说&#xff0c;以下是一些常见的操作步骤和注意事项。 首先&#xff0c;商家需要在亚马逊广告平台注册并创建广告账户。亚马逊广告平台提供了专门的自助式广告管理工具&#xff0c;商家可以通过该…

数据结构-图的最小生成树

最小生成树介绍 最小生成树(Minimum Cost Spanning Tree)是代价最小的连通网的生成树&#xff0c;即该生成树上的边的权值和最小 最小生成树的性质&#xff1a; 必须使用且仅使用连通网中的n-1条边来联结网络中的n个顶点&#xff1b; 不能使用产生回路的边&#xff1b; 各…

linux vim 异常退出 异常处理 交换文件

交换文件 *.swp 格式 同时是隐藏的 如在vim一个文件&#xff0c; 在没有正常退出&#xff0c; 如直接断开连接 在次编辑这个文件 会出现下图的错误 解决方案&#xff1a; 直接删除这个交换文件即可 rm -fr .zen.txt.swp