Python | 深浅复制那些事儿

最近连续两次遇到因为深浅复制而导致的问题(真是记吃不记打),所以觉得有必要记录一下(长长记性)。第一次是在Python中:做用例统计处理时遇到的,使用python提供的 copy.deepcopy(object)深复制就可以解决, 第二次是在JavaScript中:前端做复制UI操作步骤时遇到的,修改复制的步骤,保存后发现原步骤也被修改了,但很遗憾 js中并没有提供深层复制的处理方法,所以需要写一个专门的方法进行处理深浅复制,并非只存在于某一种语言,而是所有带有可变类型变量的语言都会有的问题。深浅复
摘要由CSDN通过智能技术生成

最近连续两次遇到因为深浅复制而导致的问题(真是记吃不记打),所以觉得有必要记录一下(长长记性)。

  • 第一次是在Python中:做用例统计处理时遇到的,使用python提供的 copy.deepcopy(object)深复制就可以解决,
  • 第二次是在JavaScript中:前端做复制UI操作步骤时遇到的,修改复制的步骤,保存后发现原步骤也被修改了,但很遗憾 js中并没有提供深层复制的处理方法,所以需要写一个专门的方法进行处理

深浅复制,并非只存在于某一种语言,而是所有带有可变类型变量的语言都会有的问题。深浅复制的问题起源于变量的可变、不可变属性。以Python为例:

  • 不可变类型:数字、字符串、tuple元组,这类变量一旦被重新赋值,将会创建新的对象、变量对应的内存地址就会发生改变
  • 可变类型:dict、list,这类变量在进行内部元素的添加、删除、修改时,并不会影响变量本身的内存地址

假设变量的名字和值之间有一根线(指针)进行关联,对于数字、字符串、元组等不可变类型的变量来说,每次改变变量的值,这根关联的线就会移动到新的对象(新的内存地址)上;而对于dict、list这类可变类型的变量,这根线关联的值只存储了这个可变变量的内存地址(可以想象只给{}/[]分配了存储空间),真正存储的变量中元素的在其它的存储空间,dict通过链的方式将内部的元素关联起来,因此当新增、删除、修改元素时,并不影响变量的存储空间。以上仅基于自己的理解,有兴趣可以看看数据结构相关的资料。

总结一下,所谓可变、不可变是基于在不改变变量内存地址的情况下,变量内容是否可以进行改变来进行区别。

Ps:若元组(不可变)中,包含了dict、list等可变类型元素,在改变dict/list中元素时,元组内容已经发生改变。所以,元组是可变?还是不可变呢?

现在,再说回深浅复制

浅复制:是指仅复制了可变类型的变量地址(就像只记你家的门牌号)

深复制:是将可变类型变量中的每一项元素都进行了独立的复制(就像把你家里的每个人都克隆了一份一模一样的,再发了一个新房子,又是新的一家人)

- 当向可变类型变量中添加一个元素时,浅复制的对象由于只是复制了内存地址,任何引用内存地址的变量都会受到影响;而深复制与原变量已经没有关联,不受任何影响

第一次Python深浅复制实例源码:

import copy

def get_user_case_count(proj_id,startdate=None,enddate=None):
    case_status_dict = {0: '新建', 1: '成功', 2: '失败', 5: '挂起', 9: '废弃'}
    rs = select('SELECT username,status,count(*) FROM XXX GROUP BY username,status')
    data = [] # 存放最终的统计数据列表
    tmp_dict = {} # 临时存放每一个用户的用例统计数据
    for row in rs:
        if len(tmp_dict) == 0:
            tmp_dict['username'] = row[0]
        elif tmp_dict['username']!=row[0]:
            # 此处使用深复制,并清空dict下次使用;否则会将上一次的结果带入下一次
            data.append(copy.deepcopy((tmp_dict))) 
            tmp_dict.clear()
            tmp_dict['username'] = row[0]
        tmp_dict[case_status_dict[row[1]]] = row[2]
    data.append(tmp_dict)
    return data

第二次JS深浅复制实例源码:

    function copySteps(){
		// 获取选中的行进行复制,追加到表格末尾
		row = table_steps.datagrid('getSelected');
		if(row){
            // 此处,若直接使用row进行追加,则会导致选中行数据同时改变
			table_steps.datagrid('appendRow',copyDeep(row));
		}else{
			$.messager.alert("提示","请先选中需要复制的行!");
		}
	}

    
    function copyDeep(parent, child) {
		child = child || {};
		for(var i in parent) {
			if(parent.hasOwnProperty(i)) {
				if(parent[i] === null){
					child[i] = parent[i];
				}else if(typeof parent[i] === "object") {
					child[i] = (Object.prototype.toString.call(parent[i]) === "[object Array]") ? [] : {};
					extendDeep(parent[i], child[i]);
				} else {
					child[i] = parent[i];
				}
			}
		}
		return child;
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值