property內建函式深入理解
先把python核心程式設計一句話搬過來:
屬性是一種有用的特殊型別的描述符,它們是用來處理所有對例項屬性的訪問,其工作方式和我們前面說過的描述符相似,一般情況下,當你使用屬性符號來處理乙個例項屬性時,其實你是在修改這個例項的__dict__
屬性。表面上看,property()訪問和一般的屬性訪問沒有什麼區別,但是它使用了函式或者方法。property()內建函式有四個引數
property(fget=none, fset=none, fdel=none, doc=none)
四個引數都是函式,且在類宣告的時候就已經呼叫了。
ok,還是雲裡霧裡, 首先看乙個簡單例子
class
t(object):
def__init__
(self,x):
self.__x=x
defget_x
(self):
return self.__x+1
x=property(get_x)
>>>t=t(2)
>>>t.__dict__
>>>t.__dict__
dict_proxy()
如果這時候輸入t.x
會產生什麼樣的結果呢?t.__dict__['_t__x']
又是什麼呢?
首先在t.__dict
中,_t__x
這個是什麼呢?這就要說到python的私有變數 , python把兩個下劃線開頭的變數當成私有變數,也就是在__init__(self,x)
方法中的self.__x
,私有變數在**生成之前會自動轉換為長格式,也就是說__x
會轉換為._t__x
這種形式。所謂私有變數,希望外界不能隨便訪問,只能類中可以訪問,所以t.__x
是違法的,但是python提供一種訪問機制,就是t._t__x
,且這個出現在t.__dict__
當中,說明在__init__
方法中定義的屬性是例項自定義屬性。
順便提下其他兩種形式:
以單劃線開頭的,指定這個屬性是私有的,並且不可以被import匯入,也就是說當這個類被import後,不可以呼叫這個屬性
前後都有雙下劃線,是系統自帶變數/方法名
回到正事
>>>t._t__x
3>>>t.x
>4
第乙個比較好理解,關於屬性查詢策略之前在我set和get方法那篇文章詳細講過,父類中沒有_t__x
這個屬性,連__x
這個屬性都沒有(是因為__init__
方法中的屬性,類不可以直接方法,必須要定義對應的例項).父類中沒查到,就直接在自己的t.__dict__
中查詢,結果就找到了,ok,返回對應的value,就是3.
第二個當訪問t.x
的時候,先去訪問父類的t.__dict__
,之前講過,只有x是資料描述符的時候,才能去返回__get__
方法的結果,可以看到t的屬性中有這x,這裡注意了,'x':
這個property 可以看成是乙個特殊型別的描述符,與傳統的資料描述符相比,最大的不同就是: 傳統資料描述符必須要包含__set__
__get__
方法,缺一不可,但是property就不同
property(fget=none, fset=none, fdel=none, doc=none)
四個引數可以可無,沒有就none
所以訪問t.x
的時候,父類中有x屬性,發現是乙個property的描述符,且第乙個引數是get_x, 就類似於資料描述符中轉到__set__
方法一樣,轉到get_x
中得到屬性,發現返回值是self.__x+1
, 所以最後返回的是4.
如果嘗試給t.x賦值的時候,會發生什麼情況呢?
>>> t.x=100
traceback (most recent call last):
file "", line 1, in
attributeerror: can't set attribute
會出錯,原因就是property函式第二個引數為空。
同時存在fget, fset 引數的 property()
class
hidex
(object):
def__init__
(self,x):
self.x=x+1
self.y=2
defget_x
(self):
return self.__y
defset_x
(self,y):
self.__y=y+3
y=property(get_x,set_x)
檢視一下
>>>t = hidex(20)
>>> t.__dict__
當去宣告乙個例項t
的時候,__init__
方法和__set__
方法都可以影響例項的自定義屬性
其實我們發現:
>>> hidex.__dict__
dict_proxy()
這時候已經發現y已經是乙個描述符了,當在__init__
方法中對y賦值後,發現y是乙個資料描述符,2給y只是乙個過渡,2作為value 傳輸到set_x
中,還會經過乙個偽set,再新增到例項的自定義屬性中去,
我們可以對t.y
進行賦值
>>> t.y=10
>>> t.__dict__
>>> hidex.__dict__
dict_proxy()
>>> t.y
13
賦值的時候,就會呼叫set_x
, 然後把t的屬性_hidex__y
改為13.
分析下下面的**:
class
hidex
(object):
def__init__
(self,x):
self.x=x+1
self.y=2
defget_x
(self):
return self.__y
defset_x
(self,z):
self.__y=z+3
z=6z=property(get_x,set_x)
比如宣告t = hidex(20)
,可以進行t.z
的操作嗎? 可以進行t.z=30
的操作嗎?
>>> t=hidex(20)
>>> t.__dict__
>>> t.z
traceback (most recent call last):
file "", line 1, in
file "property1.py", line 6, in get_x
return self.__y
attributeerror: 'hidex' object has no attribute '_hidex__y'
>>> t.z=20
>>> t.__dict__
>>> t.z
23
為什麼會出現上面的結果呢?
當宣告乙個例項t的時候,先進行初始化,宣告了x,y 。當對t.z進行賦值的時候,根據賦值的策略,賦值首先是去父類中找這個屬性. 恰好,發現了z 是乙個property內建函式的例項,就會去呼叫裡面的fset方法,也就是會產生個__y 的屬性。
python中的 property使用
如下 class animal object def init self,name,age self.name name self.age age a animal zhuzhu 9 a.name out 3 zhuzhu a.age out 4 9 a.age 20 a.age out 5 20在...
python中 property裝飾器
python中有乙個被稱為屬性函式 property 的小概念,它可以做一些有用的事情。在這篇文章中,我們將看到如何能做以下幾點 property 考察 student 類 class student object def init self,name,score self.name name se...
python 中 property的使用
從14年下半年開始接觸到python,自學了一段時間,後又跟別人學習了下,把基礎知識基本上學過了。忽然感覺python不可能這麼簡單吧,就這麼點東西?後來看了下書,發現還有很多的高階部分。連續看了兩天,把裝飾符 看了下,記錄下。裝飾符的作用就是類裡的方法變成屬性使用,比直接呼叫方法要直接簡單 直接上...