Python中Property內建函式深入理解

2021-07-11 03:35:45 字數 4157 閱讀 9786

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不可能這麼簡單吧,就這麼點東西?後來看了下書,發現還有很多的高階部分。連續看了兩天,把裝飾符 看了下,記錄下。裝飾符的作用就是類裡的方法變成屬性使用,比直接呼叫方法要直接簡單 直接上...