亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python之路【第十二篇】:Python面向對象高級

系統 1611 0

一、反射

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。這一概念的提出很快引發了計算機科學領域關于應用反射性的研究。它首先被程序語言的設計領域所采用,并在Lisp和面向對象方面取得了成績。

?

2 python面向對象中的反射:通過字符串的形式操作對象相關的屬性。python中的一切事物都是對象(都可以使用反射)

四個可以實現自省的函數

下列方法適用于類和對象(一切皆對象,類本身也是一個對象)

導入其他模塊,利用反射查找該模塊是否存在某個方法

四種方法使用效果展示:

            
              class
            
            
               BlackMedium:
    feature
            
            =
            
              '
            
            
              Ugly
            
            
              '
            
            
              def
            
            
              __init__
            
            
              (self,name,addr):
        self.name
            
            =
            
              name
        self.addr
            
            =
            
              addr

    
            
            
              def
            
            
               sell_house(self):
        
            
            
              print
            
            (
            
              '
            
            
              %s 黑中介賣房子啦,傻逼才買呢,但是誰能證明自己不傻逼
            
            
              '
            
             %
            
              self.name)
    
            
            
              def
            
            
               rent_house(self):
        
            
            
              print
            
            (
            
              '
            
            
              %s 黑中介租房子啦,傻逼才租呢
            
            
              '
            
             %
            
              self.name)

b1
            
            =BlackMedium(
            
              '
            
            
              萬成置地
            
            
              '
            
            ,
            
              '
            
            
              回龍觀天露園
            
            
              '
            
            
              )


            
            
              #
            
            
              檢測是否含有某屬性
            
            
              print
            
            (hasattr(b1,
            
              '
            
            
              name
            
            
              '
            
            
              ))

            
            
              print
            
            (hasattr(b1,
            
              '
            
            
              sell_house
            
            
              '
            
            
              ))


            
            
              #
            
            
              獲取屬性
            
            
n=getattr(b1,
            
              '
            
            
              name
            
            
              '
            
            
              )

            
            
              print
            
            
              (n)
func
            
            =getattr(b1,
            
              '
            
            
              rent_house
            
            
              '
            
            
              )
func()


            
            
              #
            
            
               getattr(b1,'aaaaaaaa') #報錯
            
            
              print
            
            (getattr(b1,
            
              '
            
            
              aaaaaaaa
            
            
              '
            
            ,
            
              '
            
            
              不存在啊
            
            
              '
            
            
              ))


            
            
              #
            
            
              設置屬性
            
            
setattr(b1,
            
              '
            
            
              sb
            
            
              '
            
            
              ,True)
setattr(b1,
            
            
              '
            
            
              show_name
            
            
              '
            
            ,
            
              lambda
            
             self:self.name+
            
              '
            
            
              sb
            
            
              '
            
            
              )

            
            
              print
            
            (b1.
            
              __dict__
            
            
              )

            
            
              print
            
            
              (b1.show_name(b1))


            
            
              #
            
            
              刪除屬性
            
            
delattr(b1,
            
              '
            
            
              addr
            
            
              '
            
            
              )
delattr(b1,
            
            
              '
            
            
              show_name
            
            
              '
            
            
              )
delattr(b1,
            
            
              '
            
            
              show_name111
            
            
              '
            
            )
            
              #
            
            
              不存在,則報錯
            
            
              print
            
            (b1.
            
              __dict__
            
            )
          

3 為什么用反射之反射的好處

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

總之反射的好處就是,可以事先定義好接口,接口只有在被完成后才會真正執行,這實現了即插即用,這其實是一種‘后期綁定’,什么意思?即你可以事先把主要的邏輯寫好(只定義接口),然后后期再去實現接口的功能
            
          
            
              class
            
            
               FtpClient:
    
            
            
              '
            
            
              ftp客戶端,但是還么有實現具體的功能
            
            
              '
            
            
              def
            
            
              __init__
            
            
              (self,addr):
        
            
            
              print
            
            (
            
              '
            
            
              正在連接服務器[%s]
            
            
              '
            
             %
            
              addr)
        self.addr
            
            =addr
          
            
              #
            
            
              from module import FtpClient
            
            
f1=FtpClient(
            
              '
            
            
              192.168.1.1
            
            
              '
            
            
              )

            
            
              if
            
             hasattr(f1,
            
              '
            
            
              get
            
            
              '
            
            
              ):
    func_get
            
            =getattr(f1,
            
              '
            
            
              get
            
            
              '
            
            
              )
    func_get()

            
            
              else
            
            
              :
    
            
            
              print
            
            (
            
              '
            
            
              ---->不存在此方法
            
            
              '
            
            
              )
    
            
            
              print
            
            (
            
              '
            
            
              處理其他的邏輯
            
            
              '
            
            )
          

好處二:動態導入模塊(基于反射當前模塊成員)

Python之路【第十二篇】:Python面向對象高級_第1張圖片

二、 __setattr__,__delattr__,__getattr__

三者用法展示:

            
              #
            
            
              #getattr
              

# class Foo: # x=1 # def __init__(self,y): # self.y=y # # def __getattr__(self, item): # print('執行__getattr__') # # f1=Foo(10) # print(f1.y) # print(getattr(f1,'y')) #len(str) ------>str.__len__() ##delattr # # class Foo: # x=1 # def __init__(self,y): # self.y=y # # def __delattr__(self, item): # print('刪除操作__delattr__') # # f1=Foo(10) # del f1.y # print(f1.x) # #setattr 添加/修改屬性會觸發 class Foo: x =1 def __init__ (self,y): self.y = y def __setattr__ (self,key,value): print ( ' __setattr__執行 ' ) # self.key=value self. __dict__ [key]= value f1 =Foo(10 ) print (f1. __dict__ ) f1.z =2 print (f1. __dict__ )

三、包裝標準類型

包裝:python為大家提供了標準數據類型,以及豐富的內置方法,其實在很多場景下我們都需要基于標準數據類型來定制我們自己的數據類型,新增/改寫方法,這就用到了我們剛學的繼承/派生知識 其他的標準類型均可以通過下面的方式進行二次加工

            
              class
            
            
               List(list):
    
            
            
              def
            
            
               append(self,p_object):
        
            
            
              if
            
             type(p_object) 
            
              is
            
            
               str:
            
            
            
              #
            
            
               self.append(p_object)
            
            
                          super().append(p_object)
        
            
            
              else
            
            
              :
            
            
            
              print
            
            (
            
              '
            
            
              只能添加字符串類型
            
            
              '
            
            
              )
    
            
            
              def
            
            
               show_middle(self):
        mid_index
            
            =int(len(self)/2
            
              )
        
            
            
              return
            
            
               self[mid_index]



            
            
              #
            
            
               l2=List('hello world')
            
            
              
#
            
            
               print(l2,type(l2))
            
            
              
l1
            
            =List(
            
              '
            
            
              helloworld
            
            
              '
            
            
              )

            
            
              #
            
            
               print(l1,type(l1))
            
            
l1.append(123456
            
              )
l1.append(
            
            
              '
            
            
              sb
            
            
              '
            
            
              )

            
            
              print
            
            (l1)
          

?

四、isinstance(obj,cls)和issubclass(sub,super)

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

            
              class
            
            
               Foo(object):
      
            
            
              pass
            
            
              

obj  
            
            =
            
               Foo()

isinstance(obj,  Foo)
            
          

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

            
              class
            
            
               Foo:
    
            
            
              pass
            
            
              class
            
            
               Bar(Foo):
    
            
            
              pass
            
            
              
f1
            
            =
            
              Foo()

            
            
              print
            
            
              (isinstance(f1,Foo))

            
            
              print
            
            (issubclass(Bar,Foo))
          

五、__getattribute__

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

    
            
            
              def
            
            
              __getattr__
            
            
              (self, item):
        
            
            
              print
            
            (
            
              '
            
            
              執行的是getattr
            
            
              '
            
            
              )
    
            
            
              def
            
            
              __getattribute__
            
            
              (self, item):
        
            
            
              print
            
            (
            
              '
            
            
              執行的是getattribute
            
            
              '
            
            
              )
        
            
            
              raise
            
             AttributeError(
            
              '
            
            
              拋出異常了
            
            
              '
            
            
              )

f1
            
            =Foo(11
            
              )

            
            
              #
            
            
               f1.x
            
            
f1.xxxxxx  
            
              #
            
            
              不存在的屬性訪問,觸發__getattr__
            
          

六、__setitem__,__getitem__,__delitem__

            
              class
            
            
               Foo:
    
            
            
              def
            
            
              __getitem__
            
            
              (self, item):
        
            
            
              print
            
            (
            
              '
            
            
              getitem
            
            
              '
            
            
              )
        
            
            
              #
            
            
               retun self.__dict__
            
            
              def
            
            
              __setitem__
            
            
              (self, key, value):
        
            
            
              print
            
            (
            
              '
            
            
              setitem
            
            
              '
            
            
              )
        self.
            
            
              __dict__
            
            [key]=
            
              value

    
            
            
              def
            
            
              __delitem__
            
            
              (self, key):
        
            
            
              print
            
            (
            
              '
            
            
              delitem
            
            
              '
            
            
              )
        self.
            
            
              __dict__
            
            
              .pop(key)


f1
            
            =
            
              Foo()

            
            
              print
            
            (f1.
            
              __dict__
            
            
              )

            
            
              #
            
            
               f1.name='simon'
            
            
f1[
            
              '
            
            
              name
            
            
              '
            
            ]=
            
              '
            
            
              simon
            
            
              '
            
            
              
f1[
            
            
              '
            
            
              age
            
            
              '
            
            ]=28


            
              print
            
            (
            
              '
            
            
              ===========>
            
            
              '
            
            ,f1.
            
              __dict__
            
            
              )


            
            
              #
            
            
               del f1.name
            
            
              
#
            
            
               print(f1.__dict__)
            
            
              
#
            
            
               print(f1.age)
            
            
              del
            
             f1[
            
              '
            
            
              name
            
            
              '
            
            
              ]

            
            
              print
            
            (f1.
            
              __dict__
            
            )
          

七、__str__,__repr__

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

    
            
            
              def
            
            
              __str__
            
            
              (self):
        
            
            
              return
            
            
              '
            
            
              名字是【%s】 年齡是【%s】
            
            
              '
            
             %
            
              (self.name,self.age)
f1
            
            =Foo(
            
              '
            
            
              simon
            
            
              '
            
            ,18
            
              )

            
            
              print
            
            (f1) 
            
              #
            
            
              --str(f1)-->f1.__str__()
            
            
x=
            
              str(f1)

            
            
              print
            
            
              (x)


            
            
              #
            
            
              #####repr######## ,當str與repr共存是,優先使用str
            
            
              class
            
            
               Foo:
    
            
            
              def
            
            
              __init__
            
            
              (self,name,age):
        self.name
            
            =
            
              name
        self.age
            
            =
            
              age
    
            
            
              #
            
            
               def __str__(self):
            
            
              #
            
            
                   return '這是str'
            
            
              def
            
            
              __repr__
            
            
              (self):
        
            
            
              return
            
            
              '
            
            
              名字是【%s】 年齡是【%s】
            
            
              '
            
             %
            
              (self.name,self.age)
f1
            
            =Foo(
            
              '
            
            
              simon
            
            
              '
            
            ,20
            
              )

            
            
              #
            
            
              repr(f1) ----->f1.__repr__()
            
            
              print
            
            (f1) 
            
              #
            
            
              str(f1) ---->> f1.__str__() ------>f1.__repr__()
            
          

備注:

            
              '''
            
            
              
str函數或者print函數--->obj.__str__()
repr或者交互式解釋器--->obj.__repr__()
如果__str__沒有被定義,那么就會使用__repr__來代替輸出
注意:這倆方法的返回值必須是字符串,否則拋出異常

            
            
              '''
            
          

八、__format__

            format_dic=
            
              {
    
            
            
              '
            
            
              ymd
            
            
              '
            
            :
            
              '
            
            
              {0.year}{0.mon}{0.day}
            
            
              '
            
            
              ,
    
            
            
              '
            
            
              m-d-y
            
            
              '
            
            :
            
              '
            
            
              {0.mon}-{0.day}-{0.year}
            
            
              '
            
            
              ,
    
            
            
              '
            
            
              y:m:d
            
            
              '
            
            :
            
              '
            
            
              {0.year}:{0.mon}:{0.day}
            
            
              '
            
            
              

}

            
            
              class
            
            
               Date:
    
            
            
              def
            
            
              __init__
            
            
              (self,year,mon,day):
        self.year
            
            =
            
              year
        self.mon
            
            =
            
              mon
        self.day
            
            =
            
              day
    
            
            
              def
            
            
              __format__
            
            
              (self, format_spec):
        
            
            
              print
            
            (
            
              '
            
            
              我要執行啦
            
            
              '
            
            
              )
        
            
            
              print
            
            (
            
              '
            
            
              ------->
            
            
              '
            
            
              ,format_spec)
        
            
            
              if
            
            
              not
            
             format_spec 
            
              or
            
             format_spec 
            
              not
            
            
              in
            
            
               format_dic:
            format_spec
            
            =
            
              '
            
            
              ymd
            
            
              '
            
            
              
        fm 
            
            =
            
               format_dic[format_spec]
        
            
            
              return
            
            
               fm.format(self)
d1
            
            =Date(2018,12,30
            
              )
format(d1) 
            
            
              #
            
            
              d1.__format__()
            
            
              print
            
            
              (format(d1))

            
            
              print
            
            (format(d1,
            
              '
            
            
              ymd
            
            
              '
            
            
              ))

            
            
              print
            
            (format(d1,
            
              '
            
            
              y:m:d
            
            
              '
            
            
              ))

            
            
              print
            
            (format(d1,
            
              '
            
            
              m-d-y
            
            
              '
            
            
              ))

            
            
              print
            
            (format(d1,
            
              '
            
            
              fsdrerewr
            
            
              '
            
            ))
          

九、__slots__

            1.
            
              __slots__是什么
            
            
              :是一個類變量,變量值可以是列表,元祖,或者可迭代對象,也可以是一個字符串(意味著所有實例只有一個數據屬性)

            
            2
            
              .引子:使用點來訪問屬性本質就是在訪問類或者對象的__dict__屬性字典(類的字典是共享的,而每個實例的是獨立的)

            
            3
            
              .為何使用__slots__:字典會占用大量內存,如果你有一個屬性很少的類,但是有很多實例,為了節省內存可以使用__slots__取代實例的__dict__
當你定義__slots__后,
            
            
              __slots__就會為實例使用一種更加緊湊的內部表示
            
            
              。實例通過一個很小的固定大小的數組來構建,而不是為每個實例定義一個
字典,這跟元組或列表很類似。在__slots__中列出的屬性名在內部被映射到這個數組的指定小標上。使用__slots__一個不好的地方就是我們不能再給
實例添加新的屬性了,只能使用在__slots__中定義的那些屬性名。

            
            4.注意事項:
            
              __slots__的很多特性都依賴于普通的基于字典的實現
            
            
              。另外,定義了__slots__后的類不再 支持一些普通類特性了,比如多繼承。大多數情況下,你應該
只在那些經常被使用到 的用作數據結構的類上定義__slots__比如在程序中需要創建某個類的幾百萬個實例對象 。
關于__slots__的一個常見誤區是它可以作為一個封裝工具來防止用戶給實例增加新的屬性。盡管使用__slots__可以達到這樣的目的,但是這個并不是它的初衷。           更多的是用來作為一個內存優化工具。
            
          
            
              class
            
            
               Foo:
    
            
            
              __slots__
            
            =[
            
              '
            
            
              name
            
            
              '
            
            ,
            
              '
            
            
              age
            
            
              '
            
            
              ]

f1
            
            =
            
              Foo()
f1.name
            
            =
            
              '
            
            
              alex
            
            
              '
            
            
              
f1.age
            
            =18

            
              print
            
            (f1.
            
              __slots__
            
            
              )

f2
            
            =
            
              Foo()
f2.name
            
            =
            
              '
            
            
              egon
            
            
              '
            
            
              
f2.age
            
            =19

            
              print
            
            (f2.
            
              __slots__
            
            
              )


            
            
              print
            
            (Foo.
            
              __dict__
            
            
              )

            
            
              #
            
            
              f1與f2都沒有屬性字典__dict__了,統一歸__slots__管,節省內存
            
          

十、__doc__

            
              class
            
            
               Foo:
    
            
            
              '
            
            
              我是描述信息
            
            
              '
            
            
              pass
            
            
              class
            
            
               Bar(Foo):
    
            
            
              pass
            
            
              #
            
            
               print(Foo.__doc__) #該屬性無法繼承給子類
            
            
              print
            
            (Bar.
            
              __dict__
            
            
              )

            
            
              print
            
            (Bar.
            
              __doc__
            
            ) 
            
              #
            
            
              該屬性無法繼承給子類
            
          

十一、__module__和__class__

__module__表示當前操作的對象在哪個模塊

—class__ 表示當前操作的對象的類是什么

lib/simon.py

            
              #
            
            
              !/usr/bin/env python
            
            
              
#
            
            
               _*_ coding:utf-8 _*_
            
            
              class
            
            
               C:
    
            
            
              def
            
            
              __init__
            
            
              (self):
        self.name 
            
            = 
            
              '
            
            
              simon
            
            
              '
            
          

aa.py

            
              from
            
             lib.simon 
            
              import
            
            
               C

obj
            
            =
            
              C()

            
            
              print
            
            (obj.
            
              __module__
            
            ) 
            
              #
            
            
              輸出 lib.simon,即:輸出模塊
            
            
              print
            
            (obj.
            
              __class__
            
            )  
            
              #
            
            
              輸出lib.simon.C,即:輸出類
            
          

十二、__del__

            
              class
            
            
               Foo:
    
            
            
              def
            
            
              __init__
            
            
              (self,name):
        self.name
            
            =
            
              name
    
            
            
              def
            
            
              __del__
            
            
              (self):
        
            
            
              print
            
            (
            
              '
            
            
              我執行啦
            
            
              '
            
            
              )

f1
            
            =Foo(
            
              '
            
            
              simon
            
            
              '
            
            
              )


            
            
              #
            
            
               del f1    #刪除實例會觸發__del__
            
            
              del
            
             f1.name 
            
              #
            
            
              刪除實例的屬性不會觸發__del__
            
            
              print
            
            (
            
              '
            
            
              --------------------->
            
            
              '
            
            
              )


            
            
              #
            
            
              程序運行完畢會自動回收內存,觸發__del__
            
          

十三、__call__

對象后面加括號,觸發執行。

注:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對于 __call__ 方法的執行是由對象后加括號觸發的,即:對象() 或者 類()()

            
              class
            
            
               Foo:
    
            
            
              def
            
            
              __call__
            
            (self, *args, **
            
              kwargs):
        
            
            
              print
            
            (
            
              '
            
            
              實例執行啦 obj()
            
            
              '
            
            
              )

f1
            
            =
            
              Foo()

f1() 
            
            
              #
            
            
              f1的類Foo 下的__call__
            
            
              
Foo() 
            
            
              #
            
            
              Foo的類 xxx下的__call__
            
          

十四、__next__和__iter__實現迭代器協議

1、迭代器協議是指:對象必須提供一個Next方法,執行該方法要么返回迭代中的下一項,要么就引起一個StopIteration異常,以終止迭代(只能往后走不能往前退)

2、可迭代對象:實現了迭代器協議的對象(如何實現:對象內部定義一個__iter__()方法)

3、協議是一種約定,可迭代對象實現了迭代器協議,python內部工具(如for循環,sum,min,max函數等)使用迭代器協議訪問對象。

            
              class
            
            
               Foo:
    
            
            
              def
            
            
              __init__
            
            
              (self,n):
        self.n
            
            =
            
              n
    
            
            
              def
            
            
              __iter__
            
            
              (self):
        
            
            
              return
            
            
               self
    
            
            
              def
            
            
              __next__
            
            
              (self):
        
            
            
              if
            
             self.n == 13
            
              :
            
            
            
              raise
            
             StopIteration(
            
              '
            
            
              終止了
            
            
              '
            
            
              )
        self.n
            
            +=1
        
            
              return
            
            
               self.n

            
            
              #
            
            
               l=list('simon')
            
            
              
#
            
            
               for i in l:
            
            
              
#
            
            
                   print(i)
            
            
              
f1
            
            =Foo(10
            
              )

            
            
              #
            
            
               print(f1.__next__())
            
            
              
#
            
            
               print(f1.__next__())
            
            
              
#
            
            
               print(f1.__next__())
            
            
              for
            
             i 
            
              in
            
             f1: 
            
              #
            
            
              iter(f1)------------>f1.__iter__()
            
            
              print
            
            (i)
          

斐波那契數列:

            
              class
            
            
               Fib:
    
            
            
              def
            
            
              __init__
            
            
              (self):
        self._a
            
            =1
            
              
        self._b
            
            =1

    
            
              def
            
            
              __iter__
            
            
              (self):
        
            
            
              return
            
            
               self
    
            
            
              def
            
            
              __next__
            
            
              (self):
        
            
            
              if
            
             self._a > 100
            
              :
            
            
            
              raise
            
             StopIteration(
            
              '
            
            
              終止了
            
            
              '
            
            
              )
        self._a,self._b
            
            =self._b,self._a +
            
               self._b
        
            
            
              return
            
            
               self._a

f1
            
            =
            
              Fib()

            
            
              print
            
            
              (next(f1))

            
            
              print
            
            
              (next(f1))

            
            
              print
            
            
              (next(f1))

            
            
              print
            
            
              (next(f1))

            
            
              print
            
            
              (next(f1))

            
            
              print
            
            (
            
              '
            
            
              ============================
            
            
              '
            
            
              )


            
            
              for
            
             i 
            
              in
            
            
               f1:
    
            
            
              print
            
            (i)
          

十五、描述符(_get_,_set_,_delete_)

1、什么是描述符

描述符本質就是一個新式類,在這個新式類中,至少實現了__get__(),__set__(),__delete__()中的一個,這也被稱為描述符協議

__get__():調用一個屬性時,觸發

__set__():為一個屬性賦值時,觸發

__delete__():采用del刪除屬性時,觸發

            
              class
            
            
               Foo:
    
            
            
              def
            
            
              __get__
            
            
              (self, instance, owner):
        
            
            
              print
            
            (
            
              '
            
            
              =====>get方法
            
            
              '
            
            
              )

    
            
            
              def
            
            
              __set__
            
            
              (self, instance, value):
        
            
            
              print
            
            (
            
              '
            
            
              =====>set方法
            
            
              '
            
            
              )

    
            
            
              def
            
            
              __delete__
            
            
              (self, instance):
        
            
            
              print
            
            (
            
              '
            
            
              =====>delete方法
            
            
              '
            
            
              )


            
            
              class
            
            
               Bar:
    x
            
            =Foo()  
            
              #
            
            
              在何地?
            
            
              #
            
            
              在何時
            
            
b1=
            
              Bar()
b1.x

b1.x
            
            =1


            
              del
            
            
               b1.x
f1
            
            =
            
              Foo()
f1.name
            
            =
            
              '
            
            
              simon
            
            
              '
            
            
              print
            
            (f1.name)
          
          
            
              類屬性>數據描述符
            
          
            
              #
            
            
              描述符Str
            
            
              class
            
            
               Str:
    
            
            
              def
            
            
              __get__
            
            
              (self, instance, owner):
        
            
            
              print
            
            (
            
              '
            
            
              Str調用
            
            
              '
            
            
              )
    
            
            
              def
            
            
              __set__
            
            
              (self, instance, value):
        
            
            
              print
            
            (
            
              '
            
            
              Str設置...
            
            
              '
            
            
              )
    
            
            
              def
            
            
              __delete__
            
            
              (self, instance):
        
            
            
              print
            
            (
            
              '
            
            
              Str刪除...
            
            
              '
            
            
              )


            
            
              class
            
            
               People:
    name
            
            =
            
              Str()
    
            
            
              def
            
            
              __init__
            
            (self,name,age): 
            
              #
            
            
              name被Str類代理,age被Int類代理,
            
            
        self.name=
            
              name
        self.age
            
            =
            
              age



            
            
              #
            
            
              基于上面的演示,我們已經知道,在一個類中定義描述符它就是一個類屬性,存在于類的屬性字典中,而不是實例的屬性字典
            
            
              #
            
            
              那既然描述符被定義成了一個類屬性,直接通過類名也一定可以調用吧,沒錯
            
            
People.name 
            
              #
            
            
              恩,調用類屬性name,本質就是在調用描述符Str,觸發了__get__()
            
            
              
People.name
            
            =
            
              '
            
            
              egon
            
            
              '
            
            
              #
            
            
              那賦值呢,我去,并沒有觸發__set__()
            
            
              del
            
             People.name 
            
              #
            
            
              趕緊試試del,我去,也沒有觸發__delete__()
            
            
              
#
            
            
              結論:描述符對類沒有作用-------->傻逼到家的結論
            
            
              '''
            
            
              
原因:描述符在使用時被定義成另外一個類的類屬性,因而類屬性比二次加工的描述符偽裝而來的類屬性有更高的優先級
People.name #恩,調用類屬性name,找不到就去找描述符偽裝的類屬性name,觸發了__get__()

People.name='egon' #那賦值呢,直接賦值了一個類屬性,它擁有更高的優先級,相當于覆蓋了描述符,肯定不會觸發描述符的__set__()
del People.name #同上

            
            
              '''
            
            
              

數據描述符>實例屬性

            
              #
            
            
              描述符Str
            
            
              class
            
            
               Str:
    
            
            
              def
            
            
              __get__
            
            
              (self, instance, owner):
        
            
            
              print
            
            (
            
              '
            
            
              Str調用
            
            
              '
            
            
              )
    
            
            
              def
            
            
              __set__
            
            
              (self, instance, value):
        
            
            
              print
            
            (
            
              '
            
            
              Str設置...
            
            
              '
            
            
              )
    
            
            
              def
            
            
              __delete__
            
            
              (self, instance):
        
            
            
              print
            
            (
            
              '
            
            
              Str刪除...
            
            
              '
            
            
              )


            
            
              class
            
            
               People:
    name
            
            =
            
              Str()
    
            
            
              def
            
            
              __init__
            
            (self,name,age): 
            
              #
            
            
              name被Str類代理,age被Int類代理,
            
            
        self.name=
            
              name
        self.age
            
            =
            
              age


p1
            
            =People(
            
              '
            
            
              egon
            
            
              '
            
            ,18
            
              )


            
            
              #
            
            
              如果描述符是一個數據描述符(即有__get__又有__set__),那么p1.name的調用與賦值都是觸發描述符的操作,于p1本身無關了,相當于覆蓋了實例的屬性
            
            
p1.name=
            
              '
            
            
              egonnnnnn
            
            
              '
            
            
              
p1.name

            
            
              print
            
            (p1.
            
              __dict__
            
            )
            
              #
            
            
              實例的屬性字典中沒有name,因為name是一個數據描述符,優先級高于實例屬性,查看/賦值/刪除都是跟描述符有關,與實例無關了
            
            
              del
            
             p1.name
          

實例屬性>非數據描述符

            
              class
            
            
               Foo:
    
            
            
              def
            
            
               func(self):
        
            
            
              print
            
            (
            
              '
            
            
              我胡漢三又回來了
            
            
              '
            
            
              )
f1
            
            =
            
              Foo()
f1.func() 
            
            
              #
            
            
              調用類的方法,也可以說是調用非數據描述符
            
            
              
#
            
            
              函數是一個非數據描述符對象(一切皆對象么)
            
            
              print
            
            
              (dir(Foo.func))

            
            
              print
            
            (hasattr(Foo.func,
            
              '
            
            
              __set__
            
            
              '
            
            
              ))

            
            
              print
            
            (hasattr(Foo.func,
            
              '
            
            
              __get__
            
            
              '
            
            
              ))

            
            
              print
            
            (hasattr(Foo.func,
            
              '
            
            
              __delete__
            
            
              '
            
            
              ))

            
            
              #
            
            
              有人可能會問,描述符不都是類么,函數怎么算也應該是一個對象啊,怎么就是描述符了
            
            
              
#
            
            
              笨蛋哥,描述符是類沒問題,描述符在應用的時候不都是實例化成一個類屬性么
            
            
              
#
            
            
              函數就是一個由非描述符類實例化得到的對象
            
            
              
#
            
            
              沒錯,字符串也一樣
            
            
              

f1.func
            
            =
            
              '
            
            
              這是實例屬性啊
            
            
              '
            
            
              print
            
            
              (f1.func)


            
            
              del
            
             f1.func 
            
              #
            
            
              刪掉了非數據
            
            
f1.func()
          

再次驗證:實例屬性>非數據描述符

            
              class
            
            
               Foo:
    
            
            
              def
            
            
              __set__
            
            
              (self, instance, value):
        
            
            
              print
            
            (
            
              '
            
            
              set
            
            
              '
            
            
              )
    
            
            
              def
            
            
              __get__
            
            
              (self, instance, owner):
        
            
            
              print
            
            (
            
              '
            
            
              get
            
            
              '
            
            
              )

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



            
            
              #
            
            
              name是一個數據描述符,因為name=Foo()而Foo實現了get和set方法,因而比實例屬性有更高的優先級
            
            
              
#
            
            
              對實例的屬性操作,觸發的都是描述符的
            
            
r1=Room(
            
              '
            
            
              廁所
            
            
              '
            
            ,1,1
            
              )
r1.name
r1.name
            
            =
            
              '
            
            
              廚房
            
            
              '
            
            
              class
            
            
               Foo:
    
            
            
              def
            
            
              __get__
            
            
              (self, instance, owner):
        
            
            
              print
            
            (
            
              '
            
            
              get
            
            
              '
            
            
              )

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



            
            
              #
            
            
              name是一個非數據描述符,因為name=Foo()而Foo沒有實現set方法,因而比實例屬性有更低的優先級
            
            
              
#
            
            
              對實例的屬性操作,觸發的都是實例自己的
            
            
r1=Room(
            
              '
            
            
              廁所
            
            
              '
            
            ,1,1
            
              )
r1.name
r1.name
            
            =
            
              '
            
            
              廚房
            
            
              '
            
          

?總結:

1、描述符本身應該定義成新式類,被代理的類也應該是新式類

2、必須把描述符定義成這個類的代理,不能為定義到構造函數中

3、要嚴格遵循優先級,優先級由高到低分別

?

十六、__enter__和__exit__

操作文件對象的時候:

            with open(
            
              '
            
            
              text.txt
            
            
              '
            
            ,
            
              '
            
            
              r
            
            
              '
            
            
              ) as f:
        
            
            
              '
            
            
              代碼塊
            
            
              '
            
          

上述叫做上下文管理協議,即with語句,為了讓一個對象兼容with語句,必須在這個對象的類中聲明__enter__和__exit__方法

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

    
            
            
              def
            
            
              __enter__
            
            
              (self):
        
            
            
              print
            
            (
            
              '
            
            
              執行enter
            
            
              '
            
            
              )
        
            
            
              return
            
            
               self

    
            
            
              def
            
            
              __exit__
            
            
              (self, exc_type, exc_val, exc_tb):
        
            
            
              print
            
            (
            
              '
            
            
              執行exit
            
            
              '
            
            
              )


            
            
              #
            
            
               f=Open('a.txt')
            
            
with Foo(
            
              '
            
            
              a.txt
            
            
              '
            
            
              ) as f:
    
            
            
              print
            
            
              (f)
    
            
            
              print
            
            
              (f.name)
    
            
            
              print
            
            (
            
              '
            
            
              00000000000000000000
            
            
              '
            
            )
          

上述代碼分析:

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

    
            
            
              def
            
            
              __enter__
            
            
              (self):
        
            
            
              print
            
            (
            
              '
            
            
              執行enter
            
            
              '
            
            
              )
        
            
            
              return
            
            
               self

    
            
            
              def
            
            
              __exit__
            
            
              (self, exc_type, exc_val, exc_tb):
        
            
            
              print
            
            (
            
              '
            
            
              執行exit
            
            
              '
            
            
              )
        
            
            
              print
            
            
              (exc_type)
        
            
            
              print
            
            
              (exc_val)
        
            
            
              print
            
            
              (exc_tb)
        
            
            
              return
            
            
               True


            
            
              #
            
            
               f=Open('a.txt')
            
            
with Foo(
            
              '
            
            
              a.txt
            
            
              '
            
            
              ) as f:
    
            
            
              print
            
            
              (f)
    
            
            
              print
            
            (asfdreevergewafa)  
            
              #
            
            
              觸發__exit__
            
            
              print
            
            
              (f.name)

            
            
              print
            
            (
            
              '
            
            
              00000000000000000000
            
            
              '
            
            
              )


            
            
              #
            
            
              with obj as f:
            
            
              '
            
            
              代碼塊
            
            
              '
            
            

1、with obj ---->>觸發obj.
            
              __enter__
            
            
              (),拿到返回值

            
            2、as f--------->f=
            
              返回值、

            
            3、with obj as f 等同于  f=obj.
            
              __enter__
            
            
              ()

            
            4
            
              、執行代碼塊
一:沒有異常的情況下,整個代碼塊運行完畢后去觸發__exit__,它的三個參數都為None
二:有異常的情況下,從異常出現的位置直接觸發__exit__
    a: 如果__exit__的返回值為True,代表吞掉了異常
    b: 如果__exit__的返回值不為True,代表了吐出了異常
    c: 
            
            
              __exit__的運行完畢就代表了整個with語句的執行完畢
            
          

總結:

1.使用with語句的目的就是把代碼塊放入with中執行,with結束后,自動完成清理工作,無須手動干預

2.在需要管理一些資源比如文件,網絡連接和鎖的編程環境中,可以在__exit__中定制自動釋放資源的機制,你無須再去關系這個問題,這將大有用處

?


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 四虎影音 | 天天综合亚洲国产色 | 四虎永久在线观看免费网站网址 | 天天草比 | 成人国产在线视频在线观看 | 91精品国产爱久久久久久 | 国产 日韩 欧美 亚洲 | 欧美午夜片 | 亚洲国产精品综合久久网络 | 久久国产这里只有精品 | 麻豆国产原创最新在线视频 | 国产精品小视频在线观看 | 香蕉久久综合 | 国产剧情一区二区三区 | 免费中日高清无专码有限公司 | 久久看免费视频 | 欧美一级黄色片在线观看 | 毛片录像| 亚洲成人在线视频观看 | 中文字幕亚洲综合精品一区 | 日日夜夜人人 | 欧美成人精品久久精品 | 日韩久久中文字幕 | 久久婷婷国产麻豆91天堂 | 国产成人综合91精品 | 国产成人在线免费视频 | 香蕉视频一区二区 | 欧美成人性毛片免费版 | 久久er热这里只有精品23 | 日日摸夜夜嗷嗷叫日日拍 | 亚洲两性| 国产精品久久久久免费a∨ 国产精品久久久久免费视频 | 国产精品久久综合桃花网 | 日日噜噜夜夜狠视频免费 | 奇米色888| 一级毛片高清 | 九九热在线视频 | 四虎影视永久免费观看 | 亚洲精品亚洲人成人网 | 日本一区二区三区不卡在线视频 | 看一级毛片一区二区三区免费 |