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

Python之路【第十二篇】:Python面向?qū)ο蟾呒?/h1>
系統(tǒng) 1870 0

一、反射

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態(tài)或行為的一種能力(自省)。這一概念的提出很快引發(fā)了計(jì)算機(jī)科學(xué)領(lǐng)域關(guān)于應(yīng)用反射性的研究。它首先被程序語言的設(shè)計(jì)領(lǐng)域所采用,并在Lisp和面向?qū)ο蠓矫嫒〉昧顺煽儭?

?

2 python面向?qū)ο笾械姆瓷洌和ㄟ^字符串的形式操作對象相關(guān)的屬性。python中的一切事物都是對象(都可以使用反射)

四個(gè)可以實(shí)現(xiàn)自省的函數(shù)

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

導(dǎo)入其他模塊,利用反射查找該模塊是否存在某個(gè)方法

四種方法使用效果展示:

            
              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') #報(bào)錯(cuò)
            
            
              print
            
            (getattr(b1,
            
              '
            
            
              aaaaaaaa
            
            
              '
            
            ,
            
              '
            
            
              不存在啊
            
            
              '
            
            
              ))


            
            
              #
            
            
              設(shè)置屬性
            
            
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
            
            
              '
            
            )
            
              #
            
            
              不存在,則報(bào)錯(cuò)
            
            
              print
            
            (b1.
            
              __dict__
            
            )
          

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

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

總之反射的好處就是,可以事先定義好接口,接口只有在被完成后才會真正執(zhí)行,這實(shí)現(xiàn)了即插即用,這其實(shí)是一種‘后期綁定’,什么意思?即你可以事先把主要的邏輯寫好(只定義接口),然后后期再去實(shí)現(xiàn)接口的功能
            
          
            
              class
            
            
               FtpClient:
    
            
            
              '
            
            
              ftp客戶端,但是還么有實(shí)現(xiàn)具體的功能
            
            
              '
            
            
              def
            
            
              __init__
            
            
              (self,addr):
        
            
            
              print
            
            (
            
              '
            
            
              正在連接服務(wù)器[%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
            
            (
            
              '
            
            
              處理其他的邏輯
            
            
              '
            
            )
          

好處二:動(dòng)態(tài)導(dǎo)入模塊(基于反射當(dāng)前模塊成員)

Python之路【第十二篇】:Python面向?qū)ο蟾呒塤第1張圖片

二、 __setattr__,__delattr__,__getattr__

三者用法展示:

            
              #
            
            
              #getattr
              

# class Foo: # x=1 # def __init__(self,y): # self.y=y # # def __getattr__(self, item): # print('執(zhí)行__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 添加/修改屬性會觸發(fā) class Foo: x =1 def __init__ (self,y): self.y = y def __setattr__ (self,key,value): print ( ' __setattr__執(zhí)行 ' ) # self.key=value self. __dict__ [key]= value f1 =Foo(10 ) print (f1. __dict__ ) f1.z =2 print (f1. __dict__ )

三、包裝標(biāo)準(zhǔn)類型

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

            
              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
            
            (
            
              '
            
            
              執(zhí)行的是getattr
            
            
              '
            
            
              )
    
            
            
              def
            
            
              __getattribute__
            
            
              (self, item):
        
            
            
              print
            
            (
            
              '
            
            
              執(zhí)行的是getattribute
            
            
              '
            
            
              )
        
            
            
              raise
            
             AttributeError(
            
              '
            
            
              拋出異常了
            
            
              '
            
            
              )

f1
            
            =Foo(11
            
              )

            
            
              #
            
            
               f1.x
            
            
f1.xxxxxx  
            
              #
            
            
              不存在的屬性訪問,觸發(fā)__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######## ,當(dāng)str與repr共存是,優(yōu)先使用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函數(shù)或者print函數(shù)--->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
            
            (
            
              '
            
            
              我要執(zhí)行啦
            
            
              '
            
            
              )
        
            
            
              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__是什么
            
            
              :是一個(gè)類變量,變量值可以是列表,元祖,或者可迭代對象,也可以是一個(gè)字符串(意味著所有實(shí)例只有一個(gè)數(shù)據(jù)屬性)

            
            2
            
              .引子:使用點(diǎn)來訪問屬性本質(zhì)就是在訪問類或者對象的__dict__屬性字典(類的字典是共享的,而每個(gè)實(shí)例的是獨(dú)立的)

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

            
            4.注意事項(xiàng):
            
              __slots__的很多特性都依賴于普通的基于字典的實(shí)現(xiàn)
            
            
              。另外,定義了__slots__后的類不再 支持一些普通類特性了,比如多繼承。大多數(shù)情況下,你應(yīng)該
只在那些經(jīng)常被使用到 的用作數(shù)據(jù)結(jié)構(gòu)的類上定義__slots__比如在程序中需要?jiǎng)?chuàng)建某個(gè)類的幾百萬個(gè)實(shí)例對象 。
關(guān)于__slots__的一個(gè)常見誤區(qū)是它可以作為一個(gè)封裝工具來防止用戶給實(shí)例增加新的屬性。盡管使用__slots__可以達(dá)到這樣的目的,但是這個(gè)并不是它的初衷。           更多的是用來作為一個(gè)內(nèi)存優(yōu)化工具。
            
          
            
              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__了,統(tǒng)一歸__slots__管,節(jié)省內(nèi)存
            
          

十、__doc__

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

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

十一、__module__和__class__

__module__表示當(dāng)前操作的對象在哪個(gè)模塊

—class__ 表示當(dāng)前操作的對象的類是什么

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
            
            (
            
              '
            
            
              我執(zhí)行啦
            
            
              '
            
            
              )

f1
            
            =Foo(
            
              '
            
            
              simon
            
            
              '
            
            
              )


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


            
            
              #
            
            
              程序運(yùn)行完畢會自動(dòng)回收內(nèi)存,觸發(fā)__del__
            
          

十三、__call__

對象后面加括號,觸發(fā)執(zhí)行。

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

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

f1
            
            =
            
              Foo()

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

十四、__next__和__iter__實(shí)現(xiàn)迭代器協(xié)議

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

2、可迭代對象:實(shí)現(xiàn)了迭代器協(xié)議的對象(如何實(shí)現(xiàn):對象內(nèi)部定義一個(gè)__iter__()方法)

3、協(xié)議是一種約定,可迭代對象實(shí)現(xiàn)了迭代器協(xié)議,python內(nèi)部工具(如for循環(huán),sum,min,max函數(shù)等)使用迭代器協(xié)議訪問對象。

            
              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)
          

斐波那契數(shù)列:

            
              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、什么是描述符

描述符本質(zhì)就是一個(gè)新式類,在這個(gè)新式類中,至少實(shí)現(xiàn)了__get__(),__set__(),__delete__()中的一個(gè),這也被稱為描述符協(xié)議

__get__():調(diào)用一個(gè)屬性時(shí),觸發(fā)

__set__():為一個(gè)屬性賦值時(shí),觸發(fā)

__delete__():采用del刪除屬性時(shí),觸發(fā)

            
              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()  
            
              #
            
            
              在何地?
            
            
              #
            
            
              在何時(shí)
            
            
b1=
            
              Bar()
b1.x

b1.x
            
            =1


            
              del
            
            
               b1.x
f1
            
            =
            
              Foo()
f1.name
            
            =
            
              '
            
            
              simon
            
            
              '
            
            
              print
            
            (f1.name)
          
          
            
              類屬性>數(shù)據(jù)描述符
            
          
            
              #
            
            
              描述符Str
            
            
              class
            
            
               Str:
    
            
            
              def
            
            
              __get__
            
            
              (self, instance, owner):
        
            
            
              print
            
            (
            
              '
            
            
              Str調(diào)用
            
            
              '
            
            
              )
    
            
            
              def
            
            
              __set__
            
            
              (self, instance, value):
        
            
            
              print
            
            (
            
              '
            
            
              Str設(shè)置...
            
            
              '
            
            
              )
    
            
            
              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



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

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

            
            
              '''
            
            
              

數(shù)據(jù)描述符>實(shí)例屬性

            
              #
            
            
              描述符Str
            
            
              class
            
            
               Str:
    
            
            
              def
            
            
              __get__
            
            
              (self, instance, owner):
        
            
            
              print
            
            (
            
              '
            
            
              Str調(diào)用
            
            
              '
            
            
              )
    
            
            
              def
            
            
              __set__
            
            
              (self, instance, value):
        
            
            
              print
            
            (
            
              '
            
            
              Str設(shè)置...
            
            
              '
            
            
              )
    
            
            
              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
            
              )


            
            
              #
            
            
              如果描述符是一個(gè)數(shù)據(jù)描述符(即有__get__又有__set__),那么p1.name的調(diào)用與賦值都是觸發(fā)描述符的操作,于p1本身無關(guān)了,相當(dāng)于覆蓋了實(shí)例的屬性
            
            
p1.name=
            
              '
            
            
              egonnnnnn
            
            
              '
            
            
              
p1.name

            
            
              print
            
            (p1.
            
              __dict__
            
            )
            
              #
            
            
              實(shí)例的屬性字典中沒有name,因?yàn)閚ame是一個(gè)數(shù)據(jù)描述符,優(yōu)先級高于實(shí)例屬性,查看/賦值/刪除都是跟描述符有關(guān),與實(shí)例無關(guān)了
            
            
              del
            
             p1.name
          

實(shí)例屬性>非數(shù)據(jù)描述符

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

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

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

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

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

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


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

再次驗(yàn)證:實(shí)例屬性>非數(shù)據(jù)描述符

            
              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是一個(gè)數(shù)據(jù)描述符,因?yàn)閚ame=Foo()而Foo實(shí)現(xiàn)了get和set方法,因而比實(shí)例屬性有更高的優(yōu)先級
            
            
              
#
            
            
              對實(shí)例的屬性操作,觸發(fā)的都是描述符的
            
            
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是一個(gè)非數(shù)據(jù)描述符,因?yàn)閚ame=Foo()而Foo沒有實(shí)現(xiàn)set方法,因而比實(shí)例屬性有更低的優(yōu)先級
            
            
              
#
            
            
              對實(shí)例的屬性操作,觸發(fā)的都是實(shí)例自己的
            
            
r1=Room(
            
              '
            
            
              廁所
            
            
              '
            
            ,1,1
            
              )
r1.name
r1.name
            
            =
            
              '
            
            
              廚房
            
            
              '
            
          

?總結(jié):

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

2、必須把描述符定義成這個(gè)類的代理,不能為定義到構(gòu)造函數(shù)中

3、要嚴(yán)格遵循優(yōu)先級,優(yōu)先級由高到低分別

?

十六、__enter__和__exit__

操作文件對象的時(shí)候:

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

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

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

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

    
            
            
              def
            
            
              __exit__
            
            
              (self, exc_type, exc_val, exc_tb):
        
            
            
              print
            
            (
            
              '
            
            
              執(zhí)行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
            
            (
            
              '
            
            
              執(zhí)行enter
            
            
              '
            
            
              )
        
            
            
              return
            
            
               self

    
            
            
              def
            
            
              __exit__
            
            
              (self, exc_type, exc_val, exc_tb):
        
            
            
              print
            
            (
            
              '
            
            
              執(zhí)行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)  
            
              #
            
            
              觸發(fā)__exit__
            
            
              print
            
            
              (f.name)

            
            
              print
            
            (
            
              '
            
            
              00000000000000000000
            
            
              '
            
            
              )


            
            
              #
            
            
              with obj as f:
            
            
              '
            
            
              代碼塊
            
            
              '
            
            

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

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

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

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

總結(jié):

1.使用with語句的目的就是把代碼塊放入with中執(zhí)行,with結(jié)束后,自動(dòng)完成清理工作,無須手動(dòng)干預(yù)

2.在需要管理一些資源比如文件,網(wǎng)絡(luò)連接和鎖的編程環(huán)境中,可以在__exit__中定制自動(dòng)釋放資源的機(jī)制,你無須再去關(guān)系這個(gè)問題,這將大有用處

?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产精品毛片va一区二区三区 | 日本高清不卡在线 | 日韩一区二区免费视频 | 97免费视频免费视频 | 特级黄色毛片视频 | 伊人精品视频在线观看 | 成 人 黄 色视频免费播放 | 青娱乐国产在线视频 | 美女一级毛片免费不卡视频 | 毛片免费高清免费 | 国产综合社区 | 在线观看自拍视频 | 农村苗族一级特黄a大片 | 天天干天天拍天天操 | 亚洲成人国产精品 | 中文字幕不卡免费视频 | 麻豆视频一区二区 | 狼人香蕉香蕉在线视频播放 | 亚洲日韩aⅴ在线视频 | 成人免费视频在线看 | 国产日韩精品一区二区 | 欧美一级二级aaa免费视频 | 欧美专区亚洲专区 | 久久免费视屏 | 亚洲精品69 | 国内久久久久久久久久 | 波多野结衣绝顶大高潮 | 欧美久久综合九色综合 | 国产成人久久蜜一区二区 | 成人观看视频 | 亚洲三级天堂 | 青青青青青国产免费观看 | 四虎国产精品一区二区 | 久久最新 | 青草青青在线视频观看 | 欧美aⅴ在线| 2018天天干天天操 | 午夜免费福利在线观看 | 免费尤物视频 | 国产精品香蕉在线观看首页 | 美女精品 |