Python的基础--对象 转
?
對象(Objects)是python中數據的抽象,python中所有的數據均可以用對象或者是對象之間的關系來表示。每個對象均有標識符(identity)、類型(type)、值(value)。?
在python中,不存在所謂的傳值調用,一切傳遞的都是對象的引用,也可以認為是傳地址。
可變對象與不可變對象
python在heap中分配的對象分成兩類:可變對象和不可變對象。所謂可變對象指的是,對象的內容可變,而不可變對象是指對象的內容不可變。
不可變(immutable)對象:int、字符串(string)、float、數值型(number)、元組(tuple)。
可變(mutable)對象:字典型(dictionary)、列表型(list)。
一、不可變對象
由于Python中的變量存放的是對象引用,所以對于不可變對象而言,盡管對象本身不可變,但變量的對象引用是可變的。
i = 73 i += 2
(點小圖查看大圖)
從上面圖示得知,對象73和對象75并沒有變化,變化的只是創建了一個新的對象,改變了變量的對象的引用。看看下面的代碼,更能體現這一點:
#因為258是int對象,是不可變對象的。所以下面3個id的值都是一樣的,最后一句的結果也是為True #有點奇怪的是為什么在IDLE,和在腳本執行的結果不太一樣。所以下面的代碼請在腳本中執行。 print(id(258)) a = 258 print(id(a)) b = 258 print(id(b)) print(a is b)總結一下,不可變對象的優缺點。
優點是:這樣可以減少重復的值對內存空間的占用。
缺點是:我要修改這個變量綁定的值,如果內存中沒用存在該值的內存塊,那么必須重新開辟一塊內存,把新地址與變量名綁定。而不是修改變量原來指向的內存塊的值,這回給執行效率帶來一定的降低。
二、可變對象
其對象的內容是可以變化的。當對象的內容發生變化時,變量的對象引用是不會變化的。如下面的例子:
m=[5,9] m+=[6]
(點小圖查看大圖)
函數參數
?
Python函數參數對于可變對象,函數內對參數的改變會影響到原始對象;對于不可變對象,函數內對參數的改變不會影響到原始參數。原因在于:
1、可變對象,參數改變的是可變對象,其內容可以被修改。
2、不可變對象,改變的是函數內變量的指向對象。
有關可變對象和不可變對象的介紹,簡單的介紹到這里。
?
對象的回收機制
python不像C那樣需要顯式地回收對象占用的空間,python內核中有垃圾回收機制,當一個對象不可達時,就會交由垃圾回收機制處理。
一些對象引用了一些外部資源,例如打開的文件或者窗口。通常我們認為當這些對象被垃圾回收機制回收時,它占用的外部資源即被釋放。但是,垃圾回收機制并不一定會回收這些對象,因此這些對象提供了顯式的方法(通常是_close()_)用來釋放外部資源。程序中最好使用顯式的方法來釋放外部資源,一般可以使用?_try...finally_方便地釋放。
對象的類型
對象的類型幾乎影響了該對象的所有功能,在某種程度上,對象的標識符也受其類型的影響。
>>> sum = 15 >>> sum_add = 12 + 3 >>> sum is sum_add True >>> sum = 15000000 >>> sum_add = 10000000 + 5000000 >>> sum is sum_add False >>> sum_add == sum True對于不可變對象(這里是int),當我們需要一個新的對象(sum_add = 12 + 3)時,python可能會返回已經存在的某個類型和值都一致的對象(sum)的引用。當然,這里只是可能會返回已經存在的對象,要看python的具體實現。同樣是創建新的對象sum_add = 10000000 + 5000000,python并沒有把值和類型都一樣的sum返回給sum_add。
>>> value = [] >>> value_1 = [] >>> value is value_1 False >>> value == value True >>> value = value_1 = [] >>> value is value_1 True對于可變對象,當我們需要新的對象時,python一定會為我們新建一個。注意,這里value = value_1 = []將會創建一個空的列表對象,然后同時返回給value和value_1。
撲朔迷離的不可變對象
首先看下面的代碼:看我怎么改變不可變對象的值
>>> mutability = [1, 2, 3, 4] >>> immutability = (0, mutability, 5) >>> immutability (0, [1, 2, 3, 4], 5)#查看可變對象與不可變對象的標識符(內存地址) >>> id(mutability) 28356200 >>> id(immutability) 28048640#對可變對象與不可變對象都做一些改變 >>> mutability[2] = "see here!" >>> immutability (0, [1, 2, 'see here!', 4], 5)#查看改變后的可變對象與不可變對象的標識符(內存地址) >>> id(mutability) 28356200 >>> id(immutability) 28048640這里元組immutability中一個元素為可變對象列表mutability,當我們改變mutability的值時,號稱不可變對象的元組的值似乎發生了變化。這又是為什么呢?
回答這個問題前,先總結下上面這段代碼發生了什么:不可變對象A包含了一個對可變對象B的引用,可變對象B的值發生改變時,不可變對象A的值似乎會發生改變。
那么,為什么我們仍認為A是不可變對象呢?因為A仍然包含對象B,而B的標識符并沒有發生變化,也就是說A的所有元素的標識符并沒有發生變化。
看內存的布局是怎樣的:
(點小圖查看大圖)
可以看出a是一個list列表類型的對象,它是一個可變對象,所以修改它的值不會創建新的對象。但是b是一個不可變對象,只要修改它的值,就會重新創建對象,注意,這里并沒有修改它的值,因為它的所有元素的標識符并沒有變化。
再看下面的例子:
>>> a = 2 >>> b = (1, a, 3) >>> b (1, 2, 3) >>> id(a) 23112444 >>> id(b) 27983104>>> a += 10 >>> b (1, 2, 3) >>> id(b[1]) 23112444 >>> id(b) 27983104>>> id(a) 23112324在執行a+=10之前的內存布局為:
(點小圖查看大圖)
執行完a+=10的指令之后的內存布局為:
(點小圖查看大圖)
這里僅僅是原來的int(2)這個對象的引用數目減1.
在來一個狠的,在上面代碼的基礎上再來一個:
>>> b (1, 2, 3)>>> b[1] = 13 Traceback (most recent call last):File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment>>> b[1] 2通過元組類型的對象b對其中的一個int類型對象賦值,這樣的話,因為int是不可變對象,所以會重新申請新的內存,那么同樣會引起元組b中的xxx引用變量的改變,那么這樣就真正的改變了元組b對象的某個元素的標識符。導致真正的改變了不可變元組對象b,這時就會報錯。
?
?
修改上面的一些bug:
1. 首先id(a)函數是查看引用變量a所指向的對象的標識符,也就是內存地址。并不是引用變量a的內存地址。
2. 不管是元組還是列表,它們的元素存儲的都是某個真實對象的引用,并不存儲這個對象,因為python中一切皆對象。
先看一個內存結構,然后在看代碼:
(點小圖查看大圖)
?
轉載于:https://www.cnblogs.com/zengkefu/p/5506727.html
總結
以上是生活随笔為你收集整理的Python的基础--对象 转的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AJAX使用技巧:如何处理书签和翻页按扭
- 下一篇: 自制基于HMM的python中文分词器