这是Python通过引用传递的行为吗?

时间:2016-04-13 22:17:15

标签: python opencv pass-by-reference

我认为Python赋值语句是“按值传递”。例如

b=0
a=b
b=1
print(a) #prints 0
print 
(b) #prints 1

但是,在处理其他类型的数据时,我对其他行为感到困惑。从本教程on openCV我稍微修改了代码以显示两个图像。以下代码采用此图片: 并将其添加到此图像中 enter image description here

并重复此过程,添加此图片

到同一个基本图像上。

import cv2
import numpy as np

# Load two images
img1 = cv2.imread('3D-Matplotlib.png')
#img1a = img1
img1a = cv2.imread('3D-Matplotlib.png')
img2 = cv2.imread('mainlogo.png')
img3 = cv2.imread('helloo.png')
# I want to put logo on top-left corner, So I create a ROI
rows,cols,channels = img2.shape
roi = img1[20:rows+20, 20:cols+20]

rows3,cols3,channels3 = img3.shape
roi3 = img1[50:rows3+50, 50:cols3+50 ]


# Now create a mask of logo 
img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
# add a threshold
ret, mask = cv2.threshold(img2gray, 220, 255, cv2.THRESH_BINARY_INV)
#anything crossing over 220 is thelower limit
#binary threshold is 0 or 1
#anything> 220 goes to 255
#anything below 220 goes to 0-> black
#and create its inverse mask
mask_inv = cv2.bitwise_not(mask)
#do same for img3
img3gray = cv2.cvtColor(img3,cv2.COLOR_BGR2GRAY)
ret3, mask3 = cv2.threshold(img3gray, 140, 255, cv2.THRESH_BINARY_INV)
mask_inv3 = cv2.bitwise_not(mask3)


# take the ROI of the plot, and throw the mask over it 
img1_bg = cv2.bitwise_and(roi,roi,mask = mask_inv)

# Take only region of logo from logo image.
img2_fg = cv2.bitwise_and(img2,img2,mask = mask)

#do the same with the other mask
img3_bg = cv2.bitwise_and(roi3,roi3,mask = mask_inv3)
img3_fg = cv2.bitwise_and(img3,img3,mask = mask3)
#

dst = cv2.add(img1_bg,img2_fg)
dst3 = cv2.add(img3_bg,img3_fg)

img1[0:rows, 0:cols ] = dst
img1a[50:rows3+50, 50:cols3+50 ] = dst3

cv2.imshow('r1',img1)
cv2.imshow('r3',img1a)

cv2.waitKey(0)
cv2.destroyAllWindows()

在上面发布的代码中,我明白了 two different images

如果我注释掉第7行并取消注释第8行,如果它是按值传递,我会期望得到相同的结果。但我得到别的东西

两张图片都是一样的。显然,对img1的操作被“转移”到img1a,因为img1a被设置为等于img1。如果赋值语句是'按值传递'(正如我所期望的那样),则img1和img1a应该是不同的。但由于它们是相同的,我得出结论,img1是一个传递给img1a的ptr。因此,如果我尝试打印img1a,我会获得与打印img1相同的数据。

所以也许图像通过引用传递? Python中的其他哪些数据类型都是这样的?阵列?字典?或者我完全错了并且困惑。

3 个答案:

答案 0 :(得分:2)

当定义变量时,您告诉Python此名称的未来出现是指...对象。即使像a = b这样的定义也是如此。 b指的是一个对象,你告诉Python a现在也指的是那个对象。更改b引用的对象不会更改a,因为a未与b相关联;它链接到b在定义a时提到的对象。如果您有一个名为b的列表并说a = b,那么使用a更改a.append(4)当然会更改b,因为它们是同一个对象。但是,使用a = 4只是改变了a所指的对象;它不会改变b

答案 1 :(得分:1)

与Java类似,Python中的所有内容都按值传递和分配。 Python中的所有值(每个表达式和变量)都是引用(指向对象的指针),并且将一个变量分配给另一个变量使第二个变量指向与第一个变量相同的对象。

当你说你正在对img1"进行操作时,你正在做的是调用img1指向的对象上的方法(使用下标或切片语法,例如{ {1}}仍然隐式调用img1[...] = dst指向的对象上的方法,这些方法正在改变该对象。这些更改可以通过恰好指向该对象的任何其他对象指针来查看。这与传递或分配无关。调用方法不是分配或传递。如果您使用img1所做的只是各种内容分配给变量img1(即img1),您确实会看到这样的语句永远不会产生影响在img1 = something指向的对象上。这就是按价值分配的方式。

答案 2 :(得分:-2)

有两种类型的对象:可变和不可变,如下所述: https://en.wikibooks.org/wiki/Python_Programming/Data_Types#Mutable_vs_Immutable_Objects 以下是不可变的(其余的都是可变的,如list,dict等,甚至是用户定义的对象。): 。 int,float,long,complex 。海峡 。字节 。元组 。冷冻套装

如果将可变对象分配给变量,则会复制其引用。因此,任何一个变化都会反映在其他变化中。对于不可变的情况,情况并非如此。