Python高階 描述符

2021-10-23 10:16:51 字數 4462 閱讀 9304

什麼是描述符

如果乙個類實現了__get__()__set__()__delete__()中的任意一種方法的類,用這個類建立的物件叫做描述符物件

描述符物件賦值給另乙個類的類屬性,那麼這個類就是描述符

描述符分為兩種

1.資料描述符:同時定義了__get____set__方法的描述符稱為資料描述符

2.非資料描述符:只定義了__get__方法的描述符稱為非資料描述符

當屬性名和描述符名相同時,在訪問這個同名屬性時,如果是資料描述符就會先訪問描述符,如果是非資料描述符就會先訪問屬性

描述符作用

訪問屬性最終執行的是函式

那麼為什麼呼叫屬性會最終執行函式呢?

這是由例項物件.__getattribute__()方法控制的

def

__getattribute__

(self, key)

:"emulate type_getattro() in objects/typeobject.c"

v =object

.__getattribute__(self, key)

ifhasattr

(v,'__get__'):

return v.__get__(

none

, self)

return v

唯讀描述符

要想製作乙個唯讀的資料描述符,需要同時定義__set____get__,並在__set__中引發乙個 attributeerror 異常。定義乙個引發異常的__set__方法就足夠讓乙個描述符成為資料描述符,且是唯讀的

__get____set__方法中的引數

classm:

def__init__

(self, name)

: self.name = name

def__get__

(self, obj,

type):

print

('get第乙個引數self: '

, self.name)

print

('get第二個引數obj: '

, obj.age)

print

('get第三個引數type: '

,type

.name)

def__set__

(self, obj, value)

:# print(self.name) # age

obj.__dict__[self.name]

= value

classa:

name =

'bob'

m = m(

'age'

)def

__init__

(self, age)

: self.age = age

a = a(20)

# age是20

a.m# get第乙個引數self: age

# get第二個引數obj: 20

# get第三個引數type: bob

a.m =

30a.age # 30

總結:

self是描述符類m中的例項

obj是呼叫描述符的類a中的例項

type是呼叫描述符的類a

value是對這個屬性賦值時傳入的值,即上面的30

描述符應用

1.實現@classmethod

class

classmethod_new

(object):

def__init__

(self, func)

: self.func = func

def__get__

(self, instance, owner)

:print

(self.func, instance, owner)

defcall

(*args)

: self.func(owner,

*args)

return call

classa(

object):

m =100def

a(self)

:print

("----a 是例項方法----"

) @classmethod_new

defb(cls)

:print

("----b 是類方法方法1----"

)print

(cls.m)

print

("----b 是類方法方法2----"

) @classmethod_new

defc(cls, num1, num2)

:print

("----c 是類方法方法1----"

)print

(cls.m + num1 + num2)

print

("----c 是類方法方法2----"

)obj = a(

)obj.b(

)a.b(

)obj.c(11,

22)

2.惰性計算

class

lazyproperty

(object):

""" 實現惰性求值(訪問時才計算,並將值快取)

利用了 obj.__dict__ 優先順序高於 non-data descriptor 的特性

第一次呼叫 __get__ 以同名屬性存於例項字典中,之後就不再呼叫 __get__

"""def__init__

(self, fun)

: self.fun = fun

def__get__

(self, instance, owner)

:print

("---lazyproperty __get__---"

)if instance is

none

:return self

value = self.fun(instance)

setattr

(instance, self.fun.__name__, value)

return value

class

readonlynumber

(object):

""" 實現唯讀屬性(例項屬性初始化後無法被修改)

利用了 data descriptor 優先順序高於 obj.__dict__ 的特性

當試圖對屬性賦值時,總會先呼叫 __set__ 方法從而丟擲異常

"""def__init__

(self, value)

: self.value = value

def__get__

(self, instance, owner)

:return self.value

def__set__

(self, instance, value)

:raise attributeerror(

"'%s' is not modifiable"

% self.value

)class

circle

(object):

pi = readonlynumber(

3.14

)def

__init__

(self, radius)

: self.radius = radius

@lazyproperty

defarea

(self)

:print

('computing area'

)return self.pi * self.radius **

2print

("---1--"

)a = circle(4)

print

("---2--"

)print

(a.area)

print

("---3--"

)print

(a.area)

print

("---4--"

)

python 描述 python描述符

在python中,訪問乙個屬性的優先順序順序按照如下順序 1.類屬性2.資料描述符3.例項屬性4.非資料描述符5.getattr 方法。描述符,用一句話來說,就是將某種特殊型別的類的例項指派給另乙個類的屬性 注意 這裡是類屬性,而不是物件屬性 而這種特殊型別的類就是實現了 get set delet...

python 描述符基本

相關資料 python的描述符 下一站,我等你 描述符的本質類 python為開發者提供了乙個非常強大的功能 描述符。那什麼是描述符呢?通過檢視python的官方文件,我們知道把實現了 get set 和 delete 中的其中任意一種方法的類稱之為描述符,描述符的本質是新式類,並且被 的類 即應用...

Python 描述符練習

要求 先定義乙個溫度類,然後定義兩個描述符用於描述攝氏度和華氏度兩個屬性 要求這個兩個屬性會自動進行轉換,也就是說你可以給攝氏度這個屬性賦值,然後列印的話華氏屬性是自動轉換的結果 class celsius def init self,value 26.0 self.value float valu...