1. 程式人生 > >面向對象之內置方法續集

面向對象之內置方法續集

好處 range post 類實例化 enter iterable rep 產生 foo

接上一篇,內置方法續集:

  六、__str__,__repr__ 和 __format__

    1、作用:__str__,__repr__ 改變對象的字符串顯示

        __format__ 自定制格式化字符串

    2、示例:

技術分享圖片
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong

format_dict={
    way1:{obj.name}-{obj.addr}-{obj.type},#學校名-學校地址-學校類型
    way2:{obj.type}:{obj.name}:{obj.addr}
,#學校類型:學校名:學校地址 way3:{obj.type}/{obj.addr}/{obj.name},#學校類型/學校地址/學校名 } class School: def __init__(self,name,addr,type): self.name = name self.addr = addr self.type = type def __repr__(self): return School(%s,%s)%(self.name,self.addr) def __str__(self):
return (%s,%s)%(self.name,self.addr) def __format__(self, format_spec): if not format_spec or format_spec not in format_dict: format_spec = way1 fmt =format_dict[format_spec] return fmt.format(obj=self) s1 = School(lufei,上海,培訓機構) print(from repr:
,repr(s1)) # from repr: School(lufei,上海) print(from str:,str(s1)) # from str: (lufei,上海) print(s1) # (lufei,上海) print(format(s1,way2))# 培訓機構:lufei:上海 print(format(s1,way3)) # 培訓機構/上海/lufei print(format(s1,abcdef)) # 培訓機構/上海/lufei ‘‘‘ str函數或者print函數--->obj.__str__() repr或者交互式解釋器--->obj.__repr__() 如果__str__沒有被定義,那麽就會使用__repr__來代替輸出 ‘‘‘
View Code

  註意:__str__和__repr__方法的返回值必須是字符串,否則拋出異常。

  七、slots的用法

    1、__slots__是什麽?

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

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

    3、使用__slots__方法的好處?

      字典會占用大量內存,如果你有一個屬性很少的類,但是有很多實例,為了節省內存可以使用__slots__取代實例的__dict__

當你定義__slots__後,__slots__就會為實例使用一種更加緊湊的內部表示。實例通過一個很小的固定大小的數組來構建,而不是為每個實例定義一個

字典,這跟元組或列表很類似。在__slots__中列出的屬性名在內部被映射到這個數組的指定小標上。使用__slots__一個不好的地方就是我們不能再給

實例添加新的屬性了,只能使用在__slots__中定義的那些屬性名。

    4、註意:__slots__的很多特性都依賴於普通的基於字典的實現。另外,定義了__slots__後的類不再 支持一些普通類特性了,比如多繼承。

大多數情況下,你應該只在那些經常被使用到 的用作數據結構的類上定義__slots__比如在程序中需要創建某個類的幾百萬個實例對象 。它更多的是

用來作為一個內存優化工具。

    5、示例:

技術分享圖片
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong

class Test:
    __slots__ = [name,age]

f1 = Test()
f1.name = cc
f1.age = 21
print(f1.__slots__) # [‘name‘, ‘age‘]
#print(f1.__dict__) 報錯,f1不再有__dict__

# f1.sex = ‘male‘ 報錯,f1不能再添加屬性
print(f1.__slots__) # [‘name‘, ‘age‘]

f2 = Test()
f2.name = zm
f2.age = 19
print(f2.__slots__) # [‘name‘, ‘age‘]

 #f1與f2都沒有屬性字典__dict__了,統一歸__slots__管,節省內存
print(Test.__dict__)# {‘__module__‘: ‘__main__‘, ‘__slots__‘: [‘name‘, ‘age‘], ‘age‘: <member ‘age‘ of ‘Test‘ objects>, ‘name‘: <member ‘name‘ of ‘Test‘ objects>, ‘__doc__‘: None}
View Code 

  

  八、__next__和__iter__實現叠代器協議    

    1、關於__next__和__iter__方法的幾點解釋

    Python中關於叠代有兩個概念,第一個是Iterable,第二個是Iterator,協議規定Iterable的__iter__方法會返回一個Iterator,

Iterator的__next__方法(Python 2裏是next)會返回下一個叠代對象,如果叠代結束則拋出StopIteration異常。同時,Iterator自己也是一種Iterable,

所以也需要實現Iterable的接口,也就是__iter__,這樣在for當中兩者都可以使用。Iterator的__iter__只需要返回自己就行了。

  這樣,下面的代碼就可以工作:

  for i in my_list:
...

  for i in iter(mylist):
...

  for i in (v for v in mylist if v is not None):
...
    
2、示例1--叠代器:
技術分享圖片
class Range:
    def __init__(self,n,stop,step): # n為起點,stop為終點,step為步長
        self.n=n
        self.stop=stop
        self.step=step

    def __next__(self):
        if self.n >= self.stop:
            raise StopIteration
        x=self.n
        self.n+=self.step
        return x

    def __iter__(self):
        return self

for i in Range(1,7,3): #
    print(i)
View Code

  3、示例2--斐波拉契數列:
技術分享圖片
# 斐波那契數列
class Fib:
    def __init__(self):
        self._a=0
        self._b=1

    def __iter__(self):
        return self

    def __next__(self):
        self._a,self._b=self._b,self._a + self._b
        return self._a

f1=Fib()

print(f1.__next__())
print(next(f1))
print(next(f1))

for i in f1:
    if i > 100:
        break
    print(%s  %i,end=‘‘)
View Code

  九、 __module__和__class__

    1、__module__ 表示當前操作的對象在那個模塊、__class__ 表示當前操作的對象的類是什麽

    2、示例:

技術分享圖片
#lib/a.py

#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong

class C:

    def __init__(self):
        self.name = cc


# index.py

#from lib.a import C
obj = C()
print(obj.__module__) # 輸出 lib.a,即輸出模塊
print(obj.__class__) # 輸出lib.a.C ,輸出類
View Code

  十、__del__方法

    1、含義:析構方法,當對象在內存中被釋放時,自動觸發執行。

    2、為什麽用__del__方法?

      如果產生的對象僅僅只是python程序級別的(用戶級),那麽無需定義__del__,如果產生的對象的同時還會向操作系統發起系統調用,

即一個對象有用戶級與內核級兩種資源,比如(打開一個文件,創建一個數據庫鏈接),則必須在清除對象的同時回收系統資源,這就用到了__del__。

    3、應用場景     

      創建數據庫類,用該類實例化出數據庫鏈接對象,對象本身是存放於用戶空間內存中,而鏈接則是由操作系統管理的,

    存放於內核空間內存中當程序結束時,python只會回收自己的內存空間,即用戶態內存,而操作系統的資源則沒有被回收,

    這就需要我們定制__del__,在對象被刪除前向操作系統發起關閉數據庫鏈接的系統調用,回收資源

    4、示例:

技術分享圖片
class Foo:

    def __del__(self):
        print(執行到我啦)

f1=Foo()
del f1
print(------->)
‘‘‘
#輸出結果
執行我到啦
------->
‘‘‘
View Code

   十一、 __enter__和__exit__方法  

技術分享圖片
with open(a.txt) as f:
    pass
# 上述叫做上下文管理協議,即with語句,為了讓一個對象兼容with語句,必須在這個對象的類中聲明__enter__和__exit__方法
class Open:
    def __init__(self,filepath,mode=r,encoding=utf-8):
        self.filepath=filepath
        self.mode=mode
        self.encoding=encoding

    def __enter__(self):
        # print(‘enter‘)
        self.f=open(self.filepath,mode=self.mode,encoding=self.encoding)
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):
        ‘‘‘
        with語句中代碼塊出現異常,則with後的代碼都無法執行
        如果__exit__()返回值為True,那麽異常會被清空,就好像啥都沒發生一樣,with後的語句正常執行
        :param exc_type: 異常類型
        :param exc_val: 異常值
        :param exc_tb: 追溯信息
        :return:
        ‘‘‘
        # print(‘exit‘)
        self.f.close()
        return True
    def __getattr__(self, item): #屬性不存在時觸發
        return getattr(self.f,item)

with Open(a.txt,w) as f:
    print(f)
    f.write(aaaaaa)
    f.wasdf #拋出異常,交給__exit__處理
View Code

    使用with語句的好處:

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

在需要管理一些資源比如文件,網絡連接和鎖的編程環境中,可以在__exit__中定制自動釋放資源的機制,

你無須再去關心這個問題。

  

  十二、__call__方法

    1、使用方法:對象後面加括號,觸發執行。

    2、註意事項:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;

    而對於 __call__ 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()()。

    3、示例:

技術分享圖片
class Foo:

    def __init__(self):
        pass

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

        print(__call__)


obj = Foo() # 執行 __init__
obj()       # 執行 __call__
View Code

  十三、__doc__方法

    1、作用:查看類的描述信息。

    2、示例:

class Foo:
    我是匆匆
    pass
class Bar(Foo):
    pass
print(Foo.__doc__) # 我是匆匆
print(Bar.__doc__) # None 該屬性無法繼承給子類

    

    

    

面向對象之內置方法續集