item函數(shù),slots夷磕,迭代器協(xié)議履肃,上下文管理,元類

一. item函數(shù)

item函數(shù)可以把對(duì)象操作模擬成字典操作, item函數(shù)包括以下三個(gè)函數(shù)__getitem__坐桩,__setitem____delitem__
具體用法如下所示

class Foo:
    def __init__(self, name):
        self.name = name

    def __getitem__(self, item):
        return self.__dict__[item]

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __delitem__(self, key):
        self.__dict__.pop(key)

f = Foo('j')
print(f['name'])
f['gender'] = 'male'
print(f.__dict__)

del f['gender']
print(f.__dict__)

>>j
>>{'name': 'j', 'gender': 'male'}
>>{'name': 'j'}

二. slots

  1. __slots__是什么:是一個(gè)類變量,變量值可以是列表,元組,或者其他可迭代對(duì)象,也可以是一個(gè)字符串(意味著所有實(shí)例只有一個(gè)數(shù)據(jù)屬性)
  2. 當(dāng)一個(gè)類有較少的屬性尺棋,但是會(huì)多次實(shí)例化時(shí),為了節(jié)省內(nèi)存可以使用__slots__取代實(shí)例的__dict__
    當(dāng)你定義__slots__后。類的實(shí)例通過一個(gè)很小的固定大小的數(shù)組來構(gòu)建,而不是為每個(gè)實(shí)例定義一個(gè)
    字典,這跟元組或列表很類似绵跷。在__slots__中列出的屬性名在內(nèi)部被映射到這個(gè)數(shù)組的指定小標(biāo)上膘螟。使用__slots__的一個(gè)缺點(diǎn)就是我們不能給實(shí)例添加新的屬性,只能使用在__slots__中定義的那些屬性名。
  3. 注意事項(xiàng):__slots__的很多特性都依賴于普通的基于字典的實(shí)現(xiàn)碾局。另外,定義了__slots__后的類不再 支持一些普通類特性了,比如多繼承荆残。大多數(shù)情況下,應(yīng)該只在那些經(jīng)常被使用到 的用作數(shù)據(jù)結(jié)構(gòu)的類上定義__slots__
    __slots__可以作為一個(gè)封裝工具來防止用戶給實(shí)例增加新的屬性净当。使用__slots__可以達(dá)到這樣的目的,但是__slots__的設(shè)計(jì)初衷是一個(gè)內(nèi)存優(yōu)化工具内斯。
class Foo:
    __slots__='x'

f1=Foo()
f1.x=1
f1.y=2#報(bào)錯(cuò)
print(f1.__slots__) #使用__slots__后,不再有__dict__

class Bar:
    __slots__=['x','y']
    
n=Bar()
n.x,n.y=1,2
n.z=3#報(bào)錯(cuò)

三. 迭代器協(xié)議

迭代器協(xié)議: 對(duì)象必須提供一個(gè)next方法蚯瞧,執(zhí)行該方法要么返回迭代中的下一項(xiàng)嘿期,要么就引起一個(gè)stopIteration的異常終止迭代
遵循迭代器協(xié)議使用__iter____next__函數(shù)實(shí)現(xiàn)range函數(shù)

class Range:
    def __init__(self, value, start=0, step=1):
        self.value = value
        self.start = start
        self.step = step

    def __iter__(self):    # 使用__iter__函數(shù)為Range類增加可迭代屬性
        return self

    def __next__(self):   # 使用__next__方法得到迭代返回值
        if self.start >= self.value:
            raise StopIteration
        n = self.start
        self.start += self.step
        return n

for i in Range(3):
    print(i)

四. 上下文管理

操作文件的時(shí)候可以使用with語句,with語句遵循上下文協(xié)議埋合。使用__enter____exit__方法可以讓一個(gè)對(duì)象支持上下文協(xié)議备徐。
使用with語句可以實(shí)現(xiàn)with中的語句執(zhí)行結(jié)束后自動(dòng)完成清理工作
一般在文件操作,網(wǎng)絡(luò)連接和鎖的編程環(huán)境中甚颂,在__exit__中設(shè)計(jì)自動(dòng)釋放資源的機(jī)制蜜猾,實(shí)現(xiàn)自動(dòng)釋放資源

class Foo:
    def __init__(self, filepath, mod='r', encode='utf-8'):
        self.f = open(filepath, mod, encoding=encode)
        self.filepath = filepath
        self.mod = mod

    def write(self, line):
        self.f.write(line)

    def __getattr__(self, item):
        return getattr(self.f, item)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()
        del self.f
        return True   # 返回True可以吞掉異常,異常發(fā)生后振诬,`with`代碼塊外的語句還可以繼續(xù)執(zhí)行

    def __del__(self):
        print('close file')

with Foo('a.txt', 'w') as f:
    f.write('ddddd')
    print('------>')

五. 元類

__call__

構(gòu)造方法的執(zhí)行是由創(chuàng)建對(duì)象觸發(fā)的蹭睡,即:對(duì)象 = 類名() ;
對(duì)于 __call__方法的執(zhí)行是由對(duì)象后加括號(hào)觸發(fā)的赶么,即:對(duì)象() 或者 類()()

class Foo:
    def __init__(self):
        print('__init__')
        pass

    def __call__(self, *args, **kwargs):
        print('__call__')


obj = Foo()  # 執(zhí)行 __init__
obj()  # 執(zhí)行 __call__

>>__init__
>>__call__

metaclass

元類是類的類肩豁,是類的模板
元類是用來控制如何創(chuàng)建類的,正如類是創(chuàng)建對(duì)象的模板一樣
元類的實(shí)例為類辫呻,正如類的實(shí)例為對(duì)象
type是python的一個(gè)內(nèi)建元類清钥,用來直接控制生成類,python中任何class定義的類其實(shí)都是type類實(shí)例化的對(duì)象
創(chuàng)建類的兩種方法

# 方法一
class Foo_1:
    x = 1
    def func(self):
        print('func')
print(Foo_1.__dict__)

#{'__module__': '__main__', 
# 'x': 1, 
# 'func': <function Foo_1.func at 0x000002018A47EAE8>, 
# '__dict__': <attribute '__dict__' of 'Foo_1' objects>, 
# '__weakref__': <attribute '__weakref__' of 'Foo_1' objects>, 
# '__doc__': None}
#{'__module__': '__main__',

# 方法二
def func(self):
    print('func')
x = 1
Foo_2 = type('Foo_2', (object, ), {'func': func, 'x': 1})
print(Foo_2.__dict__)

#{'__module__': '__main__',
# 'x': 1,
# 'func': <function func at 0x0000020189FB3E18>, 
# '__dict__': <attribute '__dict__' of 'Foo_2' objects>, 
# '__weakref__': <attribute '__weakref__' of 'Foo_2' objects>, 
# '__doc__': None}

一個(gè)類沒有聲明自己的元類放闺,默認(rèn)他的元類就是type祟昭,除了使用元類type,用戶也可以通過繼承type來自定義元類

class Mymeta(type):
    def __init__(self,name,bases,dic):
        print('Mymeta.__init__')

    def __new__(cls, *args, **kwargs):
        print('Mymeta.__new__')
        return type.__new__(cls,*args,**kwargs)

    def __call__(self, *args, **kwargs):
        print('Mymeta.__call__')
        obj=self.__new__(self)
        self.__init__(self,*args,**kwargs)
        return obj

class Foo(object,metaclass=Mymeta):
    def __init__(self,name):
        print('Foo.__init__')
        self.name=name
    def __new__(cls, *args, **kwargs):
        print('Foo.__new__')
        return object.__new__(cls)

f = Foo('Joe')

>>Mymeta.__new__
>>Mymeta.__init__
>>Mymeta.__call__
>>Foo.__new__
>>Foo.__init__

名字加括號(hào)的本質(zhì)(即,任何name()的形式),都是先找到name的父類,然后執(zhí)行:父類.__call__

父類.__call__一般做兩件事:
調(diào)用父類.__new__方法并返回一個(gè)對(duì)象
調(diào)用父類.__init__方法對(duì)子類進(jìn)行初始化

class 定義Foo,并指定元類為Mymeta,這就相當(dāng)于要用Mymeta創(chuàng)建一個(gè)新的對(duì)象Foo,于是相當(dāng)于執(zhí)行
Foo=Mymeta('foo',(...),{...})
因此我們可以看到,只定義class就會(huì)有如下執(zhí)行效果

Mymeta.__new__
Mymeta.__init__

實(shí)際上class Foo(metaclass=Mymeta)是觸發(fā)了Foo=Mymeta('Foo',(...),{...})操作,
遇到了名字加括號(hào)的形式,即Mymeta(...),于是就去找Mymeta的父類type,然后執(zhí)行type.__call__(...)方法
于是觸發(fā)Mymeta.__new__方法得到一個(gè)具體的對(duì)象,然后觸發(fā)Mymeta.__init__方法對(duì)對(duì)象進(jìn)行初始化

f=Foo('Joe')的原理同上

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末怖侦,一起剝皮案震驚了整個(gè)濱河市篡悟,隨后出現(xiàn)的幾起案子谜叹,更是在濱河造成了極大的恐慌,老刑警劉巖搬葬,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荷腊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡急凰,警方通過查閱死者的電腦和手機(jī)停局,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來香府,“玉大人,你說我怎么就攤上這事码倦∑蠛ⅲ” “怎么了袁稽?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵歹撒,是天一觀的道長锹杈。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么旧烧? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任杖小,我火速辦了婚禮昂勉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布戳稽。 她就那樣靜靜地躺著,像睡著了一般吓妆。 火紅的嫁衣襯著肌膚如雪赊时。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天行拢,我揣著相機(jī)與錄音祖秒,去河邊找鬼。 笑死舟奠,一個(gè)胖子當(dāng)著我的面吹牛竭缝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播沼瘫,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼抬纸,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了耿戚?” 一聲冷哼從身側(cè)響起湿故,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤阿趁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后坛猪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脖阵,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年墅茉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了命黔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡就斤,死狀恐怖悍募,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情洋机,我是刑警寧澤搜立,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站槐秧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏忧设。R本人自食惡果不足惜刁标,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望址晕。 院中可真熱鬧膀懈,春花似錦、人聲如沸谨垃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刘陶。三九已至胳赌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間匙隔,已是汗流浹背疑苫。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纷责,地道東北人捍掺。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像再膳,于是被迫代替她去往敵國和親挺勿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理喂柒,服務(wù)發(fā)現(xiàn)不瓶,斷路器禾嫉,智...
    卡卡羅2017閱讀 134,628評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法湃番,內(nèi)部類的語法夭织,繼承相關(guān)的語法,異常的語法吠撮,線程的語...
    子非魚_t_閱讀 31,597評(píng)論 18 399
  • 1.元類 1.1.1類也是對(duì)象 在大多數(shù)編程語言中尊惰,類就是一組用來描述如何生成一個(gè)對(duì)象的代碼段。在Python中這...
    TENG書閱讀 1,255評(píng)論 0 3
  • 以前總是聽哈佛大學(xué)凌晨3點(diǎn)4點(diǎn)還有學(xué)子在圖書館奮斗在一線泥兰,現(xiàn)在也總算是能夠體會(huì)了弄屡,當(dāng)你特別想要去做一件事情...
    熙熙Breathe閱讀 376評(píng)論 0 6
  • 作者:Yvonne ?? 編輯:阿拉 《指數(shù)型組織》: 有人問,學(xué)那么多有什么用鞋诗?從指數(shù)型思維看膀捷,量的累積初期你看...
    福州十點(diǎn)讀書會(huì)閱讀 299評(píng)論 1 0