python提供了有序(sequence)類型(字串,元組,列表都是有序類型),並且提供了特殊的文法來方便對這些類型進行操作,最常用的有切片操作。同一有序類型的對象之間支援”+”操作符,用來連成一個新的有序對象,有序對象也可以與一個整數進行相乘,得到一個新的有序對象。在調試的時候,我經常使用這樣的語句來列印一個分割行:print ‘-‘ * 50。在對有序類型進行“*” 或者 “+”操作的時候,要千萬小心。今天,我的同事就遇到了非常鬱悶的問題。看下面一段代碼:
#coding=gbkclass Point(object): def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return '(%d, %d)' % (self.x, self.y)itemList = [Point(-1, -1)] * 5# 對列表元素進行賦值
for i in range(5): itemList[i].x = i itemList[i].y = i print itemList
上面的代碼建立一個包含5個Point對象的列表,然後在一個for迴圈中對列表中的每個對象的屬性進行賦值。運行上面的代碼,在螢幕上顯示的結果是什嗎?是 [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)] 嗎? 這段代碼把我們都欺騙了。結果是:[(4, 4), (4, 4), (4, 4), (4, 4), (4, 4)]。為什麼會這樣呢?答案在於參考型別與實值型別。[Point(-1, –1)] * 5,返回一個包含五個元素的列表,列表中的元素其實引用的是同一個對象,使用for迴圈在對列表進行初始化的時候,修改的其實是同一個對象的值。所以,結果就…… 一開始,我們鬱悶了很長時候,誰也沒意識到這個問題。在調試了許久之後才發現,哦,原來上帝在這裡。只要作簡單的修改,結果就會是我們想要的:
# ...# itemList = [Point(-1, -1)] * 5itemList = [Point(-1, -1) for i in range(5)]# ...