这是Python';s通过引用传递';行为?
我认为Python赋值语句是“按值传递”。比如说这是Python';s通过引用传递';行为?,python,opencv,pass-by-reference,Python,Opencv,Pass By Reference,我认为Python赋值语句是“按值传递”。比如说 b=0 a=b b=1 print(a) #prints 0 print (b) #prints 1 然而,在处理其他类型的数据时,我被一种不同的行为弄糊涂了。在本教程中,我稍微修改了代码以显示两幅图像。下面的代码采用此图像: 并将其添加到此图像中 并重复此过程,添加此图像 在相同的基础图像上 import cv2 import numpy as np # Load two images img1 = cv2.imread('3D-Ma
b=0
a=b
b=1
print(a) #prints 0
print
(b) #prints 1
然而,在处理其他类型的数据时,我被一种不同的行为弄糊涂了。在本教程中,我稍微修改了代码以显示两幅图像。下面的代码采用此图像:
并将其添加到此图像中
并重复此过程,添加此图像
在相同的基础图像上
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()
在上面发布的代码中,我得到
如果我注释掉第7行并取消注释第8行,如果它是按值传递的,我将期望得到相同的结果。但我还有别的事
两幅图像是相同的。显然,对img1的操作被“转移”到img1a,因为img1a被设置为等于img1。如果赋值语句是“按值传递”(正如我从python中所期望的那样),那么img1和img1a应该是不同的。但由于它们是相同的,我得出结论,img1是传递给img1a的ptr。因此,如果我尝试打印img1a,我将获得与打印img1相同的数据
那么图像可能是通过引用传递的?Python中还有哪些其他数据类型的行为是这样的?阵列?字典?或者我完全错了,并且感到困惑。就像在Java中一样,Python中的所有内容都是通过值传递和赋值的。Python中的所有值(每个表达式和变量)都是引用(指向对象的指针),将一个变量赋给另一个变量会使第二个变量指向与第一个变量相同的对象
当您说您正在“对img1进行操作”时,您所做的是调用由
img1
指向的对象上的方法(使用下标或切片语法,例如img1[…]=dst
,仍然隐式调用由img1
指向的对象上的方法),这些方法正在变异该对象。这些变化可以通过恰好指向该对象的任何其他对象指针看到。这与传球或分配无关。调用方法不是赋值或传递。如果您对img1
所做的只是将各种内容分配给变量img1
(即img1=something
),那么您确实会看到这样的语句对img1a
指向的对象没有影响。这就是按值赋值的含义。有两种类型的对象:可变对象和不可变对象,如前所述:
以下是不可变的(其余都是可变的,如list、dict等,甚至是用户定义的对象):
. int、float、long、复数
. str
. 字节
. 元组
. 凝固
如果将可变对象指定给变量,则会复制其引用。因此,其中一个方面的任何变化都会反映在另一个方面。至于不可变,情况并非如此 定义变量时,您告诉Python这个名称的未来出现是指。。。对象这甚至适用于像
a=b
这样的定义b
引用一个对象,您告诉Pythona
现在也引用该对象。更改b
引用的对象不会更改a
,因为a
未链接到b
;它链接到定义a
时引用的b
对象。如果你有一个名为b
的列表,并且说a=b
,那么用类似a.append(4)
的东西来更改a
当然会更改b
,因为它们是同一个对象。然而,使用a=4
只是改变a
所指的对象;它不会改变Python的传递行为,请参见否:Python以完全相同的方式传递所有对象,与对象的易变性无关。这可以通过打印调用外部和函数内部对象的id
来确认。感谢您的评论,但我仍然感到困惑。在案例#1中(当我设置img1a=cv2.imread('3D-Matplotlib.png'))时,到img1a的转换如预期的那样出现。但在案例#2中(当我设置img1a=img1时),对img1a的操作似乎被忽略了,我看到了img1的两个副本。这是因为在#2的情况下,变量img1a指向与img1相同的位吗?下面是简单的代码a和b,它们被设置为一些数字。然后将a设置为等于b。然后我“操纵”b。但a不会改变。这是不同的行为。请看我对zondo下面评论的评论。请看这个代码有两个列表,a和b。b被初始化。a等于b。然后将一个元素附加到列表b中。然后打印出列表a和b会得到不同的结果。列表a包含带有附加元素的原始列表。但是b所指的对象是空的!如果我使用b=b+[3]而不是b.append([3]),那么列表a和b是不同的,并且列表a引用的对象没有更改。列表b包含了预期的新元素。因此,使用函数“+”向列表中追加元素似乎与使用.append方法不同。我很困惑。这个线程和许多其他线程使用两种子程序来说明它们之间的区别——我们用来调用过程和函数的子程序。其思想是,您只能通过使用关键字“return”从子例程内部获取信息。这一理念与“范围”理念紧密相连。但是,在我上面的示例中,没有函数或返回参数的使用。.append()
对列表本身起作用。它会在末尾添加一个新项目。它返回None
,但对列表本身执行一些操作。因此,当您执行b.append([3])
时,列表会更改,但是b
会重新分配给.append()
返回的内容:无
。当您执行b=b+[3]
时,b+[3]
是一个新列表,其中包含b
的项目加上三个。然后将b
分配给该新列表,并且a
不会更改。