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

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

2015/9/29Python基礎(20):類的授權

2019-11-14 16:59:00
字體:
來源:轉載
供稿:網友

類的授權
1.包裝
包裝在Python編程世界中時經常會被提到的一個術語。它是一個通用的名字,意思是對一個已存在的對象進行包裝,不管它是數據類型,還是一段代碼,可以是對一個已存在的對象,增加新的,刪除不要的,或者修改其他已存在的功能。
在Python2.2以前,從Python的標準類型子類化或派生類都是不允許的,即使你現在可以這么做,這種做法也并不多。你可以包裝任何類型作為一個類的核心成員,以使新對象的行為模仿你想要的數據類型中已存在的行為,并且去掉你不希望存在的行為;它可能會要做一些額外的事情。這就是“包裝類型”。在附錄中,我們還將討論如何擴充Python,包裝的另一種形式。
包裝包括定義一個類,它的實例擁有標準類型的核心行為,但它也通過新的或最新的功能,甚至可能通過訪問實際數據的不同方法得到提高。
還可以包裝類,但這不會有太大的用途,因為已經有擁有操作對象的機制,并且在之前已經描述過,我們采用派生對標準類型有對其進行包裝的方式。

2.實現授權
授權是包裝的一個特性,可用于簡化處理有關dictating功能,采用已存在的功能達到最大限度的代碼重用。
包裝一個類型通常是對已存在的類型的一些定制。我們在前面提到過,這種方法可以新建,修改或者刪除原有產品的功能。其它的則保持原樣,或者保留已存功能和行為。授權的過程,即是所有更新的功能都是有新類的某部分來處理,但已存在的功能就授權給對象的默認屬性。
實現授權的關鍵點就是覆蓋__getattr__()方法,在代碼中包含一個對getattr()內建函數的調用。特別地,調用getattr()以得到默認對象屬性(數據屬性或者方法)并返回它以便訪問或調用。特殊方法__getattr__()的工作方式是,當搜索一個屬性時,任何局部對象(定制的對象)首先被找到。如果搜索失敗了,則__getattr__()會被調用。然后調用getattr()得到一個對象的默認行為。
也就是說,引用一個屬性時,Python解釋器將試著在局部名稱空間中查找那個名字,比如一個自定義的方法或者局部實例屬性。如果沒有在局部字典中找到,則搜索類名稱空間,以防一個類屬性被訪問。最后,如果兩類搜索都失敗了,搜索對原對象開始授權請求,此時,__getattr__()會被調用。

包裝對象的簡例
這個類幾乎可以包裝任何對象,提供基本功能。比如使用rePR()和str()來處理字符串表示法, 定制由get()方法處理,它刪除包裝并且返回原始對象,所以保留的功能都授權給對象的本地屬性,在必要時,可又__getattr__()獲得。

>>> class WrapMe(object):  def __init__(self, obj):    self.__data = obj  def get(self):    return self.__data  def __repr__(self):    return `self.__data`  def __str__(self):    return str(self.__data)  def __getattr__(self, attr):    return getattr(self.__data, attr)

 

我們使用復數來舉第一個例子,因為復數有數據屬性及conjugate()內建方法。

>>> wrappedComplex = WrapMe(3.3+1.2j)>>> wrappedComplex(3.3+1.2j)>>> wrappedComplex.real3.3>>> wrappedComplex.imag1.2>>> wrappedComplex.conjugate()(3.3-1.2j)>>> wrappedComplex.get()(3.3+1.2j)

 

一旦我們創建了包裝的對象類型,只要由交互解釋器調用repr(),就可以得到一個字符串表示,然后我們訪問了復數的三種屬性,而這在類中一種都沒有定義。對這種屬性的訪問,是通過__getattr__()方法,授權給對象。最終調用的get()方法沒有授權,因為它是為我們對象單獨定義的。
然后是一個列表的例子

>>> wrappedList = WrapMe([123, 'foo', 45.67])>>> wrappedList.append('bar')>>> wrappedList.append(123)>>> wrappedList[123, 'foo', 45.67, 'bar', 123]>>> wrappedList.index(45.67)2>>> wrappedList.count(123)2>>> wrappedList.pop()123>>> wrappedList[123, 'foo', 45.67, 'bar']


注意,盡管我們正在我們的例子中使用實例,它們展示的行為與他們包裝的數據類型非常相似。然后需要明白,只有已存在的屬性是在此代碼中授權的。
但是也不是所有的行為都能被訪問,比如:

>>> wrappedList[3]Traceback (most recent call last):File "<pyshell#29>", line 1, in <module>wrappedList[3]TypeError: 'WrapMe' object does not support indexing

對于列表的索引切片操作,它是內建于類型中的,而不是像append()方法那樣作為屬性存在的。所以不能被訪問。從另一個角度來說,切片操作符是序列類型的一部分,并不是通過__getitem__()這樣的特殊方法來實現的。
我們有一種“作弊”的方法,訪問實際對象,然后用它的切片能力:

>>> realList = wrappedList.get()>>> realList[3]'bar'

這就是我們實現get()方法的原因了,我們可以從訪問調用中直接訪問對象的屬性,而忽略局部變量。
這里是簡單包裝類的例子。我們還剛開始接觸使用類型模擬來進行類自定義。你將會發現你可以進行無限多的改進,來進一步增加代碼的用途。

更新簡單的包裹類
創建時間,修改時間,及訪問時間是文件的幾個常見屬性。我們將給一個類添加時間屬性,創建時間('ctime')是實例化的時間,修改時間('mtime')是核心數據升級的時間,而訪問時間('atime')是最后一次對象數據值被獲取或者屬性被訪問的時間戳。
我們更新前面定義的類,創建一個模塊twrapme.py
代碼如下:

from time import time, ctimeclass TimeWrapMe(object):    def __init__(self, obj):        self.__data = obj        self.__ctime = self.__mtime = /               self.__atime = time()     def get(self):        self.__atime = time()        return self.__data    def gettimeval(self, t_type):        if not isinstance(t_type, str) or /           t_type[0] not in 'cma':            raise TypeError, /                  "argument of 'c', 'm', or 'a' req'd"        return getattr(self, '_%s__%stime' % /                       (self.__class__.__name__, t_type[0]))            def gettimestr(self, t_type):        return ctime(self.gettimeval(t_type))    def set(self, obj):        self.__data = obj        self.__mtime = self.atime = time()        def __repr__(self):        self.__atime = time()        return `self.__data`    def __str__(self):        self.__atime = time()        return str(self.__data)    def __getattr__(self, attr):        self.__atime = time()        return getattr(self.__data, attr)

 

測試如下:

>>> TimeWrappedObj = TimeWrapMe(123)>>> TimeWrappedObj.gettimestr('c')'Tue Sep 29 17:25:11 2015'>>> TimeWrappedObj.gettimestr('m')'Tue Sep 29 17:25:11 2015'>>> TimeWrappedObj.gettimestr('a')'Tue Sep 29 17:25:11 2015'>>> TimeWrappedObj123>>> TimeWrappedObj.gettimestr('c')'Tue Sep 29 17:25:11 2015'>>> TimeWrappedObj.gettimestr('m')'Tue Sep 29 17:25:11 2015'>>> TimeWrappedObj.gettimestr('a')'Tue Sep 29 17:25:26 2015'>>> TimeWrappedObj.set('Update time!')>>> TimeWrappedObj.gettimestr('m')'Tue Sep 29 17:28:06 2015'>>> TimeWrappedObj'Update time!'>>> TimeWrappedObj.gettimestr('c')'Tue Sep 29 17:25:11 2015'>>> TimeWrappedObj.gettimestr('m')'Tue Sep 29 17:28:06 2015'>>> TimeWrappedObj.gettimestr('a')'Tue Sep 29 17:28:19 2015'

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 芦山县| 且末县| 柳州市| 泰来县| 宿松县| 固安县| 永兴县| 甘洛县| 林西县| 五台县| 台湾省| 苍溪县| 阳谷县| 淮北市| 吕梁市| 扶风县| 义乌市| 嘉峪关市| 河北区| 易门县| 新蔡县| 焉耆| 信丰县| 东丽区| 正蓝旗| 沂源县| 滨州市| 怀集县| 泸水县| 繁峙县| 吴堡县| 渑池县| 宿州市| 玛沁县| 闽侯县| 商河县| 闽侯县| 锡林郭勒盟| 交城县| 二手房| 武清区|