Python进阶 拷贝、with-2.2深拷贝、浅拷贝
1. 目的
现在有个需求,遍历当前程序的文件夹,获取到所有文件,然后调用了一个函数对这些文件简单的测试了一下
代码简单的测试如下:
import os def count_file(files): """ 测试列表中,非隐藏文件的个数 :param files: :return: """ # 4. 提出隐藏文件名 temp = "" for temp in files: if temp.startswith("."): files.remove(temp) # 5. 排序打印测试 files.sort() for file in files: print(file) # 1. 遍历出当前文件夹中所有的文件 file_names = os.listdir(".") print("-" * 30) # 2. 打印所有的文件名 for file in file_names: print(file) print("-" * 30) # 2. 调用一个函数,用来测试除了隐藏文件之外的文件的个数 count_file(file_names) print("-" * 30) # 3. 打印所有的文件名 for file in file_names: print(file)
运行效果:
看到有什么问题吗?
有没有发现在调用函数count_file
之后,原来的列表也被修改了,在开发过程中,往往要保留原列表的样子,此时为了能够在调用count_file
时,不让这个函数对原数据修改,需要将备份传递,而不是默认的引用传递
2. 拷贝的方式
拷贝:就是复制,但是在Python中有2种不同的拷贝程度
- 深拷贝
- 浅拷贝
3. 浅拷贝
浅拷贝:对于一个对象的顶层拷贝
通俗的理解是:拷贝了引用,并没有拷贝内容
4. 深拷贝
深拷贝:对于一个对象所有层次的拷贝(递归)
进一步理解深拷贝
5. 拷贝的其他方式
切片
表达式可以复制一个序列(例如列表等)
- 字典的copy方法可以拷贝一个字典
6. 注意点
6.1 浅拷贝对不可变类型和可变类型的copy不同
copy.copy
对于可变类型,会进行浅拷贝copy.copy
对于不可变类型,不会拷贝,仅仅是指向
In [88]: a = [11,22,33] In [89]: b = copy.copy(a) In [90]: id(a) Out[90]: 59275144 In [91]: id(b) Out[91]: 59525600 In [92]: a.append(44) In [93]: a Out[93]: [11, 22, 33, 44] In [94]: b Out[94]: [11, 22, 33] In [95]: a = (11,22,33) In [96]: b = copy.copy(a) In [97]: id(a) Out[97]: 58890680 In [98]: id(b) Out[98]: 58890680
6.2 copy.copy
和copy.deepcopy
的区别
copy.copy
说明:
copy.copy
不是因为遇到了不可变类型才不拷贝的,而是最多就只拷贝最顶层
copy.deepcopy
7. 总结
拷贝其实很简单,只是有时仅仅是最顶层的那个引用拷贝了,有时又编程了递归拷贝,到底用哪种?
简单来说,如果浅拷贝能用则用,否则再用深拷贝,这样节省内存
8. 作业
解决刚开始时,所说的问题
import os import copy def count_file(files): """ 测试列表中,非隐藏文件的个数 :param files: :return: """ # 4. 提出隐藏文件名 temp = "" for temp in files: if temp.startswith("."): files.remove(temp) # 5. 排序打印测试 files.sort() for file in files: print(file) # 1. 遍历出当前文件夹中所有的文件 file_names = os.listdir(".") print("-" * 30) # 2. 打印所有的文件名 for file in file_names: print(file) print("-" * 30) # 2. 调用一个函数,用来测试除了隐藏文件之外的文件的个数 count_file(copy.deepcopy(file_names)) # ----------这行修改了------------ print("-" * 30) # 3. 打印所有的文件名 for file in file_names: print(file)
运行效果如下: