一,對象可以修改
對象是可以修改的,通過對一個對象的屬性進行賦值就可以修改該對象的狀態了。
1.比如,要改變一個矩形的大小而不改變位置,就可以只修改寬度和高度,如下所示:
>>> square_box.width = square_box.width + 50
>>> square_box.height = square_box.height + 100
2.我們可以寫專門的函數來修改對象。比如grow_rectangle這個函數就接收一個矩形對象和 dwidth 與 dheight兩個數值,然后把這兩個數值加到矩形的寬度和高度值上。
>>> def grow_rectangle(rect, dwidth, dheight):
... rect.width += dwidth
... rect.height += dheight
...
具體的效果:
>>> square_box.width,square_box.height
(150.0, 300.0)
>>> grow_rectangle(square_box, 50, 100) //調用函數grow_rectangle,並賦值width50,height值100
>>> square_box.width,square_box.height //打印函數調用后的值
(200.0, 400.0)
在函數的內部,rect 是 square_box 的一個別名,所以當函數修改了 rect 的時候,square_box 就得到了相應的修改。
二,復制
1.別名有可能讓程序讀起來有困難,因為在一個位置做出的修改,有可能導致另外一個位置發生不可預知的情況。這樣也很難去追蹤指向一個對象的所有變量。
所以就可以不用別名,而用復制對象的方法。copy 模塊包含了一個名叫 copy 的函數,可以復制任意對象:
>>> p1 = Point()
>>> p1.x = 3.0
>>> p1.y = 4.0
>>> import copy
>>> p2 = copy.copy(p1)
>>> p2
<__main__.Point object at 0x10abe9048>
雖然p1和 p2包含的數據是相同的,但並不是同一個點對象。
>>> print_point(p1)
(3, 4)
>>> print_point(p2)
(3, 4)
>>> p1 == p2
False
>>> p1 is p2
False
從 is 運算符的執行結果來看,p1和 p2不是同一個對象。
但我本想着是 == 運算符應該得到的是 True,因為這兩個點包含的數據是一樣的。但對於實例來說,==運算符的默認行為就跟 is 運算符是一樣的;
因為,它也還是檢查對象的身份,而不是對象的相等性。這是因為我用的類是用戶自定義的,Python 不知道如何去衡量是否相等,至少是現在還不能。
注意,【==運算符的實現需要運算符重載,來實現,也就是多態的一種;也就是對用戶自定義類型,需要用戶自定義運算符,而不能簡單地繼續用內置運算符。因為自定義類型的運算是 Python 沒法確定的,得用戶自己來確定】
2.如果你用 copy.copy 復制了一個矩形,你會發現該函數復制了矩形對象,但沒有復制內嵌的點對象。
>>> box2 = copy.copy(square_box)
>>> box2 is square_box
False
>>> box2.corner is square_box.corner
True //如果復制成功,這里應該是False
下圖展示了此時的類圖的情況,這種運算叫做淺復制,因為復制了對象與對象內包含的所有引用,但不復制內嵌的對象。
3.copy 模塊還提供了一個名為 deepcopy (深復制)的方法,這樣就能把內嵌的對象也復制了。
>>> box3 = copy.deepcopy(square_box)
>>> box3 is square_box
False
>>> box3.corner is square_box.corner
False //這里是False,示意內嵌對象復制成功
box3和 square_box 就是完全隔絕開,沒有公用內嵌對象,徹底不會相互干擾的兩個對象了。
結束。