什麼是描述符
如果乙個類實現了__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...