国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

python描述符descriptor(二)

2019-11-14 17:41:21
字體:
來源:轉載
供稿:網友

python內置的描述符

python有些內置的描述符對象,PRoperty、staticmethod、classmethod,python實現如下:

class Property(object):    def __init__(self,getf,setf,delf,doc):        self.getf=getf        self.setf=setf        self.delf=delf        self.doc=doc    def __get__(self,instance,own=None):        if instance is None:            return self        if  self.getf is None:            raise AttributeError        return self.getf(instance)    def __set__(self,instance,value):        if self.setf is None:            raise AttributeError        self.setf(instance,value)    def __del__(self,instance):        if self.delf is None:            raise AttributeError            self.delf(instance)class StaticMethod(object):    def __init__(self,func):        self.func=func    def __get__(self,instance,own=None):        return self.funcclass ClassMethod(object):    def __init__(self,func):        self.func=func    def __get__(self,instance,own=None):        if own is None:            own=type(instance)        def callfunc(*args):            return self.func(own,*args)        return callfunc

為屬性值設置別名

有時候你想用一個屬性名作為另一個屬性名的別名,比如設置一些屬性的默認值必須和其他屬性的當前值一樣,而且還需要獨立的設置和刪除。

class DefaultAlias(object):    def __init__(self,name):        self.name=name    def __get__(self,instance,own):        if instance is None:  #類屬性訪問時            return self        return getattr(instance,self.name).title()class Person(object):    def __init__(self,name,aliasname=None):        self.name=name        if aliasname is not None:            self.aliasname=aliasname    aliasname=DefaultAlias('name')
>>> p=Person('sam')>>> p.aliasname'Sam'>>> p.aliasname='jack'>>> p.aliasname'jack'>>> del p.aliasname>>> p.aliasname'Sam'

這樣就為屬性name設置了一個別名aliasname,或者說把aliasname的值存儲在了name中。DefaultAlias并不是數據描述符,因為它沒有__set__方法,而是一個non-data描述符。所以我們給一個實例屬性賦值時(p.aliasname='jack'),實例會正常地記錄屬性,而且實例屬性會覆蓋掉類屬性。這樣aliasname屬性就能單獨的設置而不影響name屬性了。當我們del p.aliasname時,刪除了實例的屬性,類屬性又會再次顯現出來。

對于某些開發的類,如果要保持后續版本的兼容性,可以用新名稱來命名方法和屬性,同時保留舊名字的可用性。

class OldAlias(object):    def __init__(self,name,oldname):        self.name=name        self.oldname=oldname    def _warn(self):        print 'use %r,not %r'%(self.name,self.oldname)    def __get__(self,instance,own):        self._warn()        if instance is None:              return self        return getattr(instance,self.name)    def __set__(self,instance,value):        self._warn()        setattr(instance,self.name,value)    def __del__(self,instance):        self._warn()        delattr(instance,self.name)class NewClass(object):    def __init__(self,newname):        self.newname=newname    oldname=OldAlias('newname','oldname')
>>> c=NewClass('a')>>> c.oldnameuse 'newname',not 'oldname''a'

使用這個類的舊代碼會使用類屬性oldname,同時一個警告信息被打印,鼓勵用戶使用新屬性newname。

緩存屬性值

根據需求計算實例屬性或類屬性的值,并提供自動化的緩存。

class CachedAttribute(object):    def __init__(self,method,name=None):        self.method=method        self.name=name if name else method.__name__    def __get__(self,instance,own):        if instance is None:            return self        result=self.method(instance)        setattr(instance,self.name,result)        return resultclass MyObject(object):    def __init__(self,n):        self.n=n    @CachedAttribute    def square(self):        return self.n*self.n
>>> m=MyObject(2)>>> m.square4>>> m.n=5>>> m.square4>>> del m.square>>> m.square25

在首次訪問m.square后,square屬性就被緩存在實例m中,當改變實例屬性n時,square屬性不會改變。如果需要清除緩存,del m.square即可,再次訪問m.square屬性square的值會被再次計算。

緩存類屬性:

class CachedClassAttribute(CachedAttribute):    def __get__(self,instance,own):        return super(CachedClassAttribute,self).__get__(own,own)class MyClass(object):    class_attr=24    @CachedClassAttribute    def square(cls):        return cls.class_attr*cls.class_attr

這樣類的所有實例都有同樣的緩存值了:

>>> a=MyClass()>>> b=MyClass()>>> a.square>>> print a.square576>>> print b.square576>>> print MyClass.square576

  


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 延寿县| 阜南县| 商丘市| 百色市| 罗城| 沅陵县| 东乡族自治县| 高雄市| 长汀县| 平乐县| 洱源县| 榆中县| 永昌县| 梁平县| 韶山市| 阳谷县| 五寨县| 和静县| 竹山县| 屏东市| 修文县| 武清区| 咸丰县| 安福县| 河东区| 北碚区| 临潭县| 浦城县| 烟台市| 通许县| 海安县| 台南市| 乌鲁木齐市| 临朐县| 罗源县| 田阳县| 合川市| 宜川县| 芦溪县| 岳阳市| 通州市|