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

is this Python's pass by reference' behavior?

我以为 Python 赋值语句是 'pass by value'。例如

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

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

并重复该过程,添加这张图片

到同一个基本图像上。

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 的操作是 'carried over' 到 img1a,因为 img1a 被设置为等于 img1。如果赋值语句是 'pass by value'(正如我对 python 的预期),则 img1 和 img1a 应该不同。但由于它们是相同的,我得出结论,img1 是传递给 img1a 的 ptr。因此,如果我尝试打印 img1a,我会得到与打印 img1 相同的数据。

所以图像可能是通过引用传递的? Python 中还有哪些其他数据类型以这种方式表现?阵列?字典?还是我完全错了,一头雾水。

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

当你说你正在制作 "manipulations onto img1" 时,你所做的是在 img1 指向的对象上调用方法(使用下标或切片语法,例如 img1[...] = dst, 仍然在 img1) 指向的对象上隐式调用方法,这些方法正在改变该对象。这些更改可以通过恰好指向该对象的任何其他对象指针看到。这与传递或分配无关。调用方法不是分配或传递。如果你对 img1 所做的只是简单地 分配 变量到变量 img1 (即 img1 = something),你确实会看到这样的陈述永远不会对 img1a 指向的对象有影响。这就是按值分配的意思。

有两种类型的对象:可变的和不可变的,如前所述: https://en.wikibooks.org/wiki/Python_Programming/Data_Types#Mutable_vs_Immutable_Objects 以下是不可变的(其余都是可变的,如列表、字典等,甚至是用户定义的对象。): .整型、浮点型、长整型、复数 .海峡 .字节 .元组 .冻结集

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

定义变量时,您是在告诉 Python 以后出现的这个名称指的是...对象。即使使用 a = b 这样的定义也是如此。 b 指的是一个对象,而您告诉 Python a 现在也指的是那个对象。更改 b 引用的对象不会更改 a,因为 a 未链接到 b;它链接到 b 在定义 a 时引用的对象。如果您有一个名为 b 的列表并说 a = b,那么将 a 更改为 a.append(4) 之类的内容当然会更改 b,因为它们是同一个对象。但是,使用 a = 4 只是改变 a 所指的对象;它不会改变 b.