Python中的descriptor描述器簡明使用指南
當定義迭代器的時候,描述是實現(xiàn)迭代協(xié)議的對象,即實現(xiàn)__iter__方法的對象。同理,所謂描述器,即實現(xiàn)了描述符協(xié)議,即__get__, __set__, 和 __delete__方法的對象。
單看定義,還是比較抽象的。talk is cheap。看代碼吧:
class WebFramework(object):
def __init__(self, name='Flask'):
self.name = name
def __get__(self, instance, owner):
return self.name
def __set__(self, instance, value):
self.name = value
class PythonSite(object):
webframework = WebFramework()
In [1]: PythonSite.webframework
Out[1]: 'Flask'
In [2]: PythonSite.webframework = 'Tornado'
In [3]: PythonSite.webframework
Out[3]: 'Tornado'
定義了一個類WebFramework,它實現(xiàn)了描述符協(xié)議__get__和__set__,該對象(類也是對象,一切都是對象)即成為了一個描述器。同時實現(xiàn)__get__和__set__的稱之為資料描述器(data descriptor)。僅僅實現(xiàn)__get__的則為非描述器。兩者的差別是相對于實例的字典的優(yōu)先級。
如果實例字典中有與描述器同名的屬性,如果描述器是資料描述器,優(yōu)先使用資料描述器,如果是非資料描述器,優(yōu)先使用字典中的屬性。
描述器的調(diào)用
對于這類魔法,其調(diào)用方法往往不是直接使用的。例如裝飾器需要用 @ 符號調(diào)用。迭代器通常在迭代過程,或者使用 next 方法調(diào)用。描述器則比較簡單,對象屬性的時候會調(diào)用。
In [15]: webframework = WebFramework() In [16]: webframework.__get__(webframework, WebFramework) Out[16]: 'Flask'
描述器的應(yīng)用
描述器的作用主要在方法和屬性的定義上。既然我們可以重新描述類的屬性,那么這個魔法就可以改變類的一些行為。最簡單的應(yīng)用則是可以配合裝飾器,寫一個類屬性的緩存。Flask的作者寫了一個werkzeug網(wǎng)絡(luò)工具庫,里面就使用描述器的特性,實現(xiàn)了一個緩存器。
class _Missing(object):
def __repr__(self):
return 'no value'
def __reduce__(self):
return '_missing'
_missing = _Missing()
class cached_property(object):
def __init__(self, func, name=None, doc=None):
self.__name__ = name or func.__name__
self.__module__ = func.__module__
self.__doc__ = doc or func.__doc__
self.func = func
def __get__(self, obj, type=None):
if obj is None:
return self
value = obj.__dict__.get(self.__name__, _missing)
if value is _missing:
value = self.func(obj)
obj.__dict__[self.__name__] = value
return value
class Foo(object):
@cached_property
def foo(self):
print 'first calculate'
result = 'this is result'
return result
f = Foo()
print f.foo # first calculate this is result
print f.foo # this is result
運行結(jié)果可見,first calculate只在第一次調(diào)用時候被計算之后就把結(jié)果緩存起來了。這樣的好處是在網(wǎng)絡(luò)編程中,對HTTP協(xié)議的解析,通常會把HTTP的header解析成python的一個字典,而在視圖函數(shù)的時候,可能不知一次的訪問這個header,因此把這個header使用描述器緩存起來,可以減少多余的解析。
描述器在python的應(yīng)用十分廣泛,通常是配合裝飾器一起使用。強大的魔法來自強大的責任。描述器還可以用來實現(xiàn)ORM中對sql語句的"預編譯"。恰當?shù)氖褂妹枋銎?,可以讓自己的Python代碼更優(yōu)雅。
相關(guān)文章
PyTorch中torch.tensor()和torch.to_tensor()的區(qū)別
在Pytorch中Tensor和tensor都用于生成新的張量,但二者并不相同,下面這篇文章主要給大家介紹了關(guān)于PyTorch中torch.tensor()和torch.to_tensor()區(qū)別的相關(guān)資料,需要的朋友可以參考下2023-01-01
Python優(yōu)雅實現(xiàn)二分查找的示例詳解
二分查找是一種高效的搜索算法,用于在有序數(shù)組中查找特定元素,本文將介紹二分查找的基本原理,并通過Python代碼進行詳細講解,需要的可以參考一下2023-07-07
用gpu訓練好的神經(jīng)網(wǎng)絡(luò),用tensorflow-cpu跑出錯的原因及解決方案
這篇文章主要介紹了用gpu訓練好的神經(jīng)網(wǎng)絡(luò),用tensorflow-cpu跑出錯的原因及解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03
Python爬蟲爬取電影票房數(shù)據(jù)及圖表展示操作示例
這篇文章主要介紹了Python爬蟲爬取電影票房數(shù)據(jù)及圖表展示操作,結(jié)合實例形式分析了Python爬蟲爬取、解析電影票房數(shù)據(jù)并進行圖表展示操作相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2020-03-03
python+adb+monkey實現(xiàn)Rom穩(wěn)定性測試詳解
這篇文章主要介紹了python+adb+monkey實現(xiàn)Rom穩(wěn)定性測試詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04

