一、浅拷贝和深拷贝
以下文章讲述得很清楚:
面试题:深拷贝和浅拷贝(超级详细,有内存图)_田江的博客-CSDN博客_深拷贝和浅拷贝
python深拷贝和浅拷贝的区别 - 米 立 - 博客园 (cnblogs.com)
python修改列表的值时的地址变化,一个蛮有意思的小实验 - 雾恋过往 - 博客园 (cnblogs.com)
在python中,新建对象赋值实际上是对象的引用。当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用。
二、Python中浅拷贝
1、了解浅拷贝
列表赋值,也就是浅拷贝,属于引用类型,被赋值的列表与源列表共同引用一个地址,新列表的值发生改变,源列表的值也跟着变化。
import numpy as np
A = [0,1,2,3,4,5,6,7,8]
A1 = A;
print(A)
print(A1) #
A1.append(9)
print(A)
print(A1)
print('源列表A中各元素的地址:')
for i in range(len(A)):
print(id(A[i]))
print('拷贝列表A1中各元素的地址')
for i in range(len(A1)):
print(id(A1[i]))
从运行结果中也可以看出A和A1引用了相同的地址。
2、拷贝分为:
(1)浅拷贝
A = A1 #改变A1的值,A的值也会发生变化
(2)copy浅拷贝
A1 = A.copy()
#或者
import copy
A1 = copy.copy(A) #改变A1的值,A的值不会发生改变,除非A中包含子对象,比如:
#A = [0,1,2,[3,4,5],6,7,8]
#A copy拷贝给A1之后,若给A1添加一个元素9,则:
#A = [0,1,2,[3,4,5],6,7,8] 而A1 = [0,1,2,[3,4,5],6,7,8,9]
#若给A1[3]这个元素[3,4,5]添加一个元素9,则:
#A = [0,1,2,[3,4,5,9],6,7,8] A1 = [0,1,2,[3,4,5,9],6,7,8]
(3)深拷贝
import copy
A1 = copy.deepcopy(A) #深拷贝则是无论A有无子对象,A1改变,A也不会发生改变。
3、代码解释:
import copy
A = [0,1,2,[3,4,5],6,7,8]
A1 = A #1、浅拷贝
#A1 = copy.copy(A) #2、copy浅拷贝
#A1 = copy.deepcopy(A) #3、深拷贝
print('源列表: %s' %A)
print('拷贝列表: %s' %A1)
A1.append(9)
print('A1添加元素后的A列表:%s'%A)
print('A1添加元素后的A1列表:%s'%A1)
A1[3].append(9)
print('A1的子对象添加元素后的A列表:%s'%A)
print('A1的子元素添加元素后的A1列表:%s'%A1)
(1) 浅拷贝
结果可以看出:浅拷贝后,A和A1同步变化。
(2)copy浅拷贝
结果可以看到:copy浅拷贝之后,只有A和A1的子对象[3,4,5,9]同步变化。
(3)深拷贝
结果可以看到:A和A1不同步变化。
深拷贝为例,了解拷贝原理:
A1对A深拷贝之后,A1中的子对象[3,4,5]被拷贝到了另外的地址,其他元素依然引用源列表的地址,但在此基础上可以修改,却不改变源列表。
4、应用
python读取dicom图象,然后以不同窗宽显示:
import matplotlib.pyplot as plt
import numpy as np
import pydicom
import cv2
import SimpleITK as sitk
from skimage.morphology import disk, rectangle, binary_dilation, binary_erosion, binary_closing, binary_opening, rectangle, remove_small_objects
import scipy
def read_dicom_data(file_name):
'dicom图象读入'
file = sitk.ReadImage(file_name)
data = sitk.GetArrayFromImage(file)
print(data.shape)
data = np.squeeze(data, axis=0)
print(data.shape)
data = np.int32(data)
dicom_dataset = pydicom.dcmread(file_name)
slice_location = dicom_dataset.SliceLocation #获取层间距
return data, data.shape[0], data.shape[1], slice_location
def window(window, img_data):
'dicom图象窗宽变换'
if window == 'Lung':
img_data[img_data < -1150] = -1150
img_data[img_data > 350] = 350
elif window == 'Pelvic':
img_data[img_data < -140] = -140
img_data[img_data > 260] = 260
elif window == 'Chest':
img_data[img_data < -250] = -250
img_data[img_data > 240] = 240
elif window == 'Pelvic_scatter':
img_data[img_data < -700] = -700
img_data[img_data > 240] = 240
else:
img_data[img_data < 0] = 0
img_data[img_data > 80] = 80
return img_data
#读入dicom图像
dcm_path = 'E:/DeepLearningWorkSpace/PyCharmWorkSpace/date/CBCT_Pelvic/Pelvic-Reference-Data/CBCT/BuHui/01/20.dcm'
pixel_array, rows, columns, slice_location = read_dicom_data(dcm_path)
plt.subplot(131)
plt.title('Yuantu')
plt.imshow(pixel_array, cmap='gray')
pixel_array1 = pixel_array
pixel_array2 = pixel_array
pixel_array1 = window('Pelvic',pixel_array1)
imageData1 = (pixel_array1 - pixel_array1.min()) * 255.0 / (pixel_array1.max() - pixel_array1.min())
imageData1 = np.uint8(imageData1)
plt.subplot(132)
plt.title('window1')
plt.imshow(imageData1, cmap='gray')
pixel_array2 = window('Pelvic_scatter',pixel_array2)
imageData2 = (pixel_array2 - pixel_array2.min()) * 255.0 / (pixel_array2.max() - pixel_array2.min())
imageData2 = np.uint8(imageData2)
plt.subplot(133)
plt.title('window2')
plt.imshow(imageData2, cmap='gray')
plt.show()
使用不同的窗宽出现相同的显示结果(第二幅和第三幅图),因为:
pixel_array1 = pixel_array
pixel_array2 = pixel_array
在这里拷贝的时候用了浅拷贝,改变pixel_array1的窗宽时pixel_array和pixel_array2都发生了改变,所以window2是在改变了的pixel_array的基础上进行的。但我们不希望发生这种变化,我们希望window2是在原图上改变,所以,可以改为将浅拷贝改为copy浅拷贝或者深拷贝。
pixel_array1 = copy.copy(pixel_array)
pixel_array2 = copy.copy(pixel_array)