最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python中的descriptor描述器簡(jiǎn)明使用指南

 更新時(shí)間:2016年06月02日 17:28:30   作者:人世間  
descriptor在Python中主要被用來(lái)定義方法和屬性,使用起來(lái)相當(dāng)具有技巧性,這里我們先從基礎(chǔ)的開(kāi)始,整理一份Python中的descriptor描述器簡(jiǎn)明使用指南

當(dāng)定義迭代器的時(shí)候,描述是實(shí)現(xiàn)迭代協(xié)議的對(duì)象,即實(shí)現(xiàn)__iter__方法的對(duì)象。同理,所謂描述器,即實(shí)現(xiàn)了描述符協(xié)議,即__get__, __set__, 和 __delete__方法的對(duì)象。

單看定義,還是比較抽象的。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'

定義了一個(gè)類WebFramework,它實(shí)現(xiàn)了描述符協(xié)議__get__和__set__,該對(duì)象(類也是對(duì)象,一切都是對(duì)象)即成為了一個(gè)描述器。同時(shí)實(shí)現(xiàn)__get__和__set__的稱之為資料描述器(data descriptor)。僅僅實(shí)現(xiàn)__get__的則為非描述器。兩者的差別是相對(duì)于實(shí)例的字典的優(yōu)先級(jí)。

如果實(shí)例字典中有與描述器同名的屬性,如果描述器是資料描述器,優(yōu)先使用資料描述器,如果是非資料描述器,優(yōu)先使用字典中的屬性。

描述器的調(diào)用
對(duì)于這類魔法,其調(diào)用方法往往不是直接使用的。例如裝飾器需要用 @ 符號(hào)調(diào)用。迭代器通常在迭代過(guò)程,或者使用 next 方法調(diào)用。描述器則比較簡(jiǎn)單,對(duì)象屬性的時(shí)候會(huì)調(diào)用。

In [15]: webframework = WebFramework()

In [16]: webframework.__get__(webframework, WebFramework)
Out[16]: 'Flask'

描述器的應(yīng)用
描述器的作用主要在方法和屬性的定義上。既然我們可以重新描述類的屬性,那么這個(gè)魔法就可以改變類的一些行為。最簡(jiǎn)單的應(yīng)用則是可以配合裝飾器,寫(xiě)一個(gè)類屬性的緩存。Flask的作者寫(xiě)了一個(gè)werkzeug網(wǎng)絡(luò)工具庫(kù),里面就使用描述器的特性,實(shí)現(xiàn)了一個(gè)緩存器。

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

運(yùn)行結(jié)果可見(jiàn),first calculate只在第一次調(diào)用時(shí)候被計(jì)算之后就把結(jié)果緩存起來(lái)了。這樣的好處是在網(wǎng)絡(luò)編程中,對(duì)HTTP協(xié)議的解析,通常會(huì)把HTTP的header解析成python的一個(gè)字典,而在視圖函數(shù)的時(shí)候,可能不知一次的訪問(wèn)這個(gè)header,因此把這個(gè)header使用描述器緩存起來(lái),可以減少多余的解析。

描述器在python的應(yīng)用十分廣泛,通常是配合裝飾器一起使用。強(qiáng)大的魔法來(lái)自強(qiáng)大的責(zé)任。描述器還可以用來(lái)實(shí)現(xiàn)ORM中對(duì)sql語(yǔ)句的"預(yù)編譯"。恰當(dāng)?shù)氖褂妹枋銎?,可以讓自己的Python代碼更優(yōu)雅。

相關(guān)文章

最新評(píng)論

江油市| 宁安市| 农安县| 沽源县| 邢台县| 苏州市| 大庆市| 宽甸| 紫云| 威信县| 凌云县| 枞阳县| 沙河市| 油尖旺区| 临漳县| 双柏县| 临湘市| 都昌县| 柳林县| 吐鲁番市| 霍邱县| 墨竹工卡县| 芦山县| 淮安市| 红桥区| 仙桃市| 宜兰县| 遂川县| 安顺市| 和龙市| 甘泉县| 黑山县| 石阡县| 连南| 玉山县| 安顺市| 手游| 高青县| 恩施市| 日土县| 台湾省|