优先级队列和可变性

时间:2012-10-12 01:13:02

标签: python dictionary tuples priority-queue mutable

>>> import Queue
>>> q = Queue.PriorityQueue()
>>> a = (1, {'item': 'value'})
>>> q.put(a)
>>> q.queue
[(1, {'item': 'value'})]
>>> a[1]['count'] = 1
>>> q.queue
[(1, {'count': 1, 'item': 'value'})]
>>> q.get()
(1, {'count': 1, 'item': 'value'})

为什么添加后更改“a”的值时队列中的值会发生变化?元组本身是不可变的,但内部的字典是可变的。但我无法理解为什么队列应该被改变?

2 个答案:

答案 0 :(得分:2)

在Python中,对象通过引用传递。某些对象似乎可以作为值(例如字符串和整数)传递,但这是因为这些对象是不可变的(例如,您无法更改整数对象1的值)。

因此,当您将字典放入队列时,实际字典将弹出另一端而不是副本。

如果你想要一个副本,你可以使用字典的copy()方法,但请注意它只会给你一个浅的字典副本:副本中的键和值将是相同的对象,它们可能会自己是可变的。

答案 1 :(得分:1)

在Python中,对象既不是“通过引用”传递也不是“按值传递”。

在您的示例中,名称bool debugging = true; Mat rgb = imread("/home/brian/qt/ANPR/images/0.jpg", 0); if(debugging) { imshow("Original", rgb); } Mat grad; Mat morphKernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3)); morphologyEx(rgb, grad, MORPH_GRADIENT, morphKernel); if(debugging) { imshow("gradient morph", grad); } // binarize Mat bw; threshold(grad, bw, 0.0, 255.0, THRESH_BINARY | THRESH_OTSU); if(debugging) { imshow("threshold", bw); } // connect horizontally oriented regions Mat connected; morphKernel = getStructuringElement(MORPH_RECT, Size(10, 1)); morphologyEx(bw, connected, MORPH_CLOSE, morphKernel); if(debugging) { imshow("horizontal regions morph", connected); } // find contours Mat mask = Mat::zeros(bw.size(), CV_8UC1); vector<vector<Point> > contours2; vector<Vec4i> hierarchy; vector<Rect> txtRect; vector<vector<Point> > txtContour; findContours(connected, contours2, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); // filter contours for(int i = 0; i >= 0; i = hierarchy[i][0]) { Rect rect = boundingRect(contours2[i]); Mat maskROI(mask, rect); maskROI = Scalar(0, 0, 0); // fill the contour drawContours(mask, contours2, i, Scalar(255, 255, 255), CV_FILLED); // ratio of non-zero pixels in the filled region double r = (double)countNonZero(maskROI)/(rect.width*rect.height); /* assume at least 45% of the area is filled if it contains text */ if (r > .45 && (rect.height > 10 && rect.width > 10)) { rectangle(rgb, rect, Scalar(0, 255, 0), 2); txtRect.push_back(rect); txtContour.push_back(contours2[i]); } } if(debugging) { imshow("Characters", rgb); } Mat text(rgb.size(), CV_8U, Scalar(255)); drawContours(text, txtContour, -1, Scalar(0), FILLED, 4); if(debugging) { imshow("Detected Text", text); } 绑定到对象a

名称(1, {'item': 'value'})绑定到队列对象。

当调用q时,名称q.put(a)绑定的对象“放入”名称a绑定的对象,以便名称{{ 1}}和q指的是同一个对象。因此,当您修改该对象时,您正在修改绑定aq[0]的对象(因为它们绑定到同一个对象)。

其次,尽管元组是不可变的,但这并不意味着它不能改变。虽然作为“容器”它是不可变的并且本身不能改变,但它可以包含可变对象,因此它的内容可以改变。

这里非常有用和明确的文章: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/