物件導向進階

來源:互聯網
上載者:User

標籤:字典   size   module   setattr   建立對象   反射   layout   oldboy   not   

isinstance(obj,cls)檢查是否obj是否是類 cls 的對象

issubclass(sub, super)檢查sub類是否是 super 類的衍生類別

反射

反射的概念是由Smith在1982年首次提出的,主要是指程式可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。

hasattr(object,name)判斷object中有沒有一個name字串對應的方法或屬性

getattr(object, name, default=None),擷取屬性

setattr(x, y, v),建立屬性

delattr(x, y),刪除屬性

為什麼用反射之反射的好處

好處一:實現可插拔機制

有倆程式員,一個lili,一個是egon,lili在寫程式的時候需要用到egon所寫的類,但是egon去跟女朋友度蜜月去了,還沒有完成他寫的類,lili想到了反射,使用了反射機制lili可以繼續完成自己的代碼,等egon度蜜月回來後再繼續完成類的定義並且去實現lili想要的功能。

總之反射的好處就是,可以事先定義好介面,介面只有在被完成後才會真正執行,這實現了隨插即用,這其實是一種‘後期綁定’,什麼意思?即你可以事先把主要的邏輯寫好(只定義介面),然後後期再去實現介面的功能

好處二:動態匯入模組(基於反射當前模組成員)

 類屬性相關方法__setattr__,__delattr__,__getattr__
class Foo:    x=1    def __init__(self,y):        self.y=y    def __getattr__(self, item):        print(‘----> from getattr:你找的屬性不存在‘)    def __setattr__(self, key, value):        print(‘----> from setattr‘)        # self.key=value #這就無限遞迴了,你好好想想        # self.__dict__[key]=value #應該使用它    def __delattr__(self, item):        print(‘----> from delattr‘)        # del self.item #無限遞迴了        self.__dict__.pop(item)#__setattr__添加/修改屬性會觸發它的執行f1=Foo(10)print(f1.__dict__) # 因為你重寫了__setattr__,凡是賦值操作都會觸發它的運行,你啥都沒寫,就是根本沒賦值,除非你直接操作屬性字典,否則永遠無法賦值f1.z=3print(f1.__dict__)#__delattr__刪除屬性的時候會觸發f1.__dict__[‘a‘]=3#我們可以直接修改屬性字典,來完成添加/修改屬性的操作del f1.aprint(f1.__dict__)#__getattr__只有在使用點調用屬性且屬性不存在的時候才會觸發f1.xxxxxx三者的用法示範

 

一個靜態屬性property本質就是實現了get,set,delete三種方法

class Foo:    @property    def AAA(self):        print(‘get的時候運行我啊‘)    @AAA.setter    def AAA(self,value):        print(‘set的時候運行我啊‘)    @AAA.deleter    def AAA(self):        print(‘delete的時候運行我啊‘)#只有在屬性AAA定義property後才能定義AAA.setter,AAA.deleterf1=Foo()f1.AAAf1.AAA=‘aaa‘del f1.AAA

應用

class Goods:    def __init__(self):        # 原價        self.original_price = 100        # 折扣        self.discount = 0.8    @property    def price(self):        # 實際價格 = 原價 * 折扣        new_price = self.original_price * self.discount        return new_price    @price.setter    def price(self, value):        self.original_price = value    @price.deleter    def price(self):        del self.original_priceobj = Goods()obj.price         # 擷取商品價格obj.price = 200   # 修改商品原價print(obj.price)del obj.price     # 刪除商品原價案例一
執行個體項相關方法__setitem__,__getitem,__delitem__
class Foo:    def __init__(self,name):        self.name=name    def __getitem__(self, item):        print(self.__dict__[item])    def __setitem__(self, key, value):        self.__dict__[key]=value    def __delitem__(self, key):        print(‘del obj[key]時,我執行‘)        self.__dict__.pop(key)    def __delattr__(self, item):        print(‘del obj.key時,我執行‘)        self.__dict__.pop(item)f1=Foo(‘sb‘)f1[‘age‘]=18f1[‘age1‘]=19del f1.age1del f1[‘age‘]f1[‘name‘]=‘alex‘print(f1.__dict__)
 __str__,__repr__,__format__

改變對象的字串顯示__str__,__repr__

自定製格式化字串__format__

#_*_coding:utf-8_*___author__ = ‘Linhaifeng‘format_dict={    ‘nat‘:‘{obj.name}-{obj.addr}-{obj.type}‘,#學校名-學校地址-學校類型    ‘tna‘:‘{obj.type}:{obj.name}:{obj.addr}‘,#學校類型:學校名:學校地址    ‘tan‘:‘{obj.type}/{obj.addr}/{obj.name}‘,#學校類型/學校地址/學校名}class School:    def __init__(self,name,addr,type):        self.name=name        self.addr=addr        self.type=type    def __repr__(self):        return ‘School(%s,%s)‘ %(self.name,self.addr)    def __str__(self):        return ‘(%s,%s)‘ %(self.name,self.addr)    def __format__(self, format_spec):        # if format_spec        if not format_spec or format_spec not in format_dict:            format_spec=‘nat‘        fmt=format_dict[format_spec]        return fmt.format(obj=self)s1=School(‘oldboy1‘,‘北京‘,‘私立‘)print(‘from repr: ‘,repr(s1))print(‘from str: ‘,str(s1))print(s1)‘‘‘str函數或者print函數--->obj.__str__()repr或者互動式解譯器--->obj.__repr__()如果__str__沒有被定義,那麼就會使用__repr__來代替輸出注意:這倆方法的傳回值必須是字串,否則拋出異常‘‘‘print(format(s1,‘nat‘))print(format(s1,‘tna‘))print(format(s1,‘tan‘))print(format(s1,‘asfdasdffd‘))
__doc__查看類的描述資訊
class Foo:    ‘我是描述資訊‘    passprint(Foo.__doc__)

__module__ 表示當前操作的對象在那個模組

__class__     表示當前操作的對象的類是什麼

from lib.aa import Cobj = C()print obj.__module__  # 輸出 lib.aa,即:輸出模組print obj.__class__      # 輸出 lib.aa.C,即:輸出類

 __call__ 方法:對象後面加括弧,觸發執行。

註:構造方法的執行是由建立對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括弧觸發的,即:對象() 或者 類()()

class Foo:    def __init__(self):        pass        def __call__(self, *args, **kwargs):        print(‘__call__‘)obj = Foo() # 執行 __init__obj()       # 執行 __call__

 

物件導向進階

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.