<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python中的魔法屬性

          共 14372字,需瀏覽 29分鐘

           ·

          2021-04-10 12:03

          魔法屬性

          在Python中,所有以 __ 雙下劃線包起來(lái)的方法,都統(tǒng)稱為 Magic Method,例如類的初始化方法 __init__() ,實(shí)例對(duì)象創(chuàng)造方法 __new__()等。

          魔法屬性和方法是Python內(nèi)置的一些屬性和方法,有著特殊的含義。命名時(shí)前后加上兩個(gè)下劃線,在執(zhí)行系統(tǒng)特定操作時(shí),會(huì)自動(dòng)調(diào)用。


          常見(jiàn)的魔法屬性

          __doc__

          表示類的描述信息


          # __doc__
          class Foo:
              """ 描述類信息,這是用于測(cè)試的類 """
              
              def func(self):
                  pass

              
          # ipython 測(cè)驗(yàn)
          In [2]: Foo.__doc__
          Out[2]: ' 描述類信息,這是用于測(cè)試的類 '
              

          __module__ 和  __class__

          • __module__ 表示當(dāng)前操作的對(duì)象在那個(gè)模塊
          • __class__ 表示當(dāng)前操作的對(duì)象的類是什么

          # __module__、__class__
          # oop.py
          class Student(object):
              
              def __init__(self, name):
                  self.name = name
                  
                  
          # main.py
          from oop import Student

          s = Student()
          print(s.__module__)  # 輸出 oop 即:輸出模塊
          print(s.__class__)   # 輸出 <class 'oop.Student'> 即:輸出類

          __init__ 、__new__

          __init__() 初始化方法 和 __new__(),通過(guò)類創(chuàng)建對(duì)象時(shí),自動(dòng)觸發(fā)執(zhí)行。__new__ 是用來(lái)創(chuàng)建類并返回這個(gè)類的實(shí)例,而 __init__ 只是將傳入的參數(shù)來(lái)初始化該實(shí)例。

          • __new__() 創(chuàng)建對(duì)象時(shí)調(diào)用,會(huì)返回當(dāng)前對(duì)象的一個(gè)實(shí)例

          • __init__() 創(chuàng)建完對(duì)象后調(diào)用,對(duì)當(dāng)前對(duì)象的一些實(shí)例初始化,無(wú)返回值


          # __init__ 、 __new__
          class Student(object):

              def __init__(self, name, age):
                  print('__init__() called')
                  self.name = name
                  self.age = age

              def __new__(cls, *args, **kwargs):
                  print('__new__() called')
                  print(cls, args, kwargs)
                  return super().__new__(cls)
            

          # ipython 測(cè)驗(yàn)
          In [26]: s1 = Student('hui', age=21)
          __new__() called
          <class '__main__.Student'> ('hui',) {'age': 21}
          __init__() called

          In [27]: s2 = Student('jack', age=20)
          __new__() called
          <class '__main__.Student'> ('jack',) {'age': 20}
          __init__() called


          __del__

          當(dāng)對(duì)象在內(nèi)存中被釋放時(shí),自動(dòng)觸發(fā)執(zhí)行。

          注:此方法一般無(wú)須定義,因?yàn)镻ython是一門高級(jí)語(yǔ)言,有 內(nèi)存管理、垃圾回收機(jī)制,程序員在使用時(shí)無(wú)需關(guān)心內(nèi)存的分配和釋放,因?yàn)榇斯ぷ鞫际墙唤oPython解釋器來(lái)執(zhí)行,所以,__del__ 的調(diào)用是由解釋器在進(jìn)行垃圾回收時(shí)自動(dòng)觸發(fā)執(zhí)行的。

          # __del__
          class Foo:
              def __del__(self):
                  print('__del__() called')

                  
          # ipython 測(cè)驗(yàn)
          In [29]: f = Foo()

          In [30]: del f
          __del__() called

          __call__

          讓類的實(shí)例的行為表現(xiàn)的像函數(shù)一樣,你可以調(diào)用它們,將一個(gè)函數(shù)當(dāng)做一個(gè)參數(shù)傳到另外一個(gè)函數(shù)中等等。這是一個(gè)非常強(qiáng)大的特性,其讓Python編程更加舒適甜美。對(duì)象后面加括號(hào),觸發(fā)執(zhí)行

          注:__init__ 方法的執(zhí)行是由創(chuàng)建對(duì)象觸發(fā)的,即:對(duì)象 = 類名() ;而對(duì)于 __call__ 方法的執(zhí)行是由對(duì)象后加括號(hào)觸發(fā)的,即:對(duì)象() 或者 類()()

          __call__ 在那些 類的實(shí)例經(jīng)常改變狀態(tài)的時(shí)候會(huì)非常有效。調(diào)用這個(gè)實(shí)例是一種改變這個(gè)對(duì)象狀態(tài)的直接和優(yōu)雅的做法。用一個(gè)實(shí)例來(lái)表達(dá)最好不過(guò)了:

          # __call__
          class Rect(object)
              """
              調(diào)用實(shí)例對(duì)象來(lái)改變矩形的位置
              """

              def __init__(self, x, y):

                  # x, y代表矩形坐標(biāo)
                  self.x, self.y = x, y

              def __call__(self, x, y):        
                  # 改變實(shí)體的位置
                  self.x, self.y = x, y


          # ipython 測(cè)驗(yàn)
          In [33]: r = Rect(1010)

          In [34]: r.x, r.y
          Out[34]: (1010)

          In [35]: r(00)

          In [36]: r.x, r.y
          Out[36]: (00)

          In [37]: r(100100)

          In [38]: r.x, r.y
          Out[38]: (100100)

          __dict__

          類或?qū)ο笾械乃袑傩?/p>

          類的實(shí)例屬性屬于對(duì)象;類中的類屬性和方法等屬于類,即:

          # __dict__
          class Student(object):

              def __init__(self, name, age):
                  self.name = name
                  self._age = age

              @property
              def age(self):
                  return self._age

              
          # ipython 測(cè)驗(yàn)
          In [47]: # 獲取類屬性

          In [48]: Student.__dict__
          Out[48]:
          mappingproxy({'__module__''__main__',
                        '__init__': <function __main__.Student.__init__(self, name, age)>,
                        'age': <property at 0x210e2a005e8>,
                        '__dict__': <attribute '__dict__' of 'Student' objects>,
                        '__weakref__': <attribute '__weakref__' of 'Student' objects>,
                        '__doc__'None})

          In [49]: # 獲取實(shí)例對(duì)象的屬性

          In [50]: s = Student('hui'21)

          In [51]: s.__dict__
          Out[51]: {'name''hui''_age'21}

          In [52]: s2 = Student('jack'20)

          In [53]: s2.__dict__
          Out[53]: {'name''jack''_age'20}

          __str__

          如果一個(gè)類中定義了__str__方法,那么在打印 對(duì)象 時(shí),默認(rèn)輸出該方法的返回值。

          In [65]: # __str__
              ...: class Foo(object):
              ...:     pass
              ...:

          In [66]: f = Foo()

          In [67]: print(f)
          <__main__.Foo object at 0x00000210E2715608>

          In [68]: class Foo(object):
              ...:
              ...:     def __str__(self):
              ...:         return '< Custom Foo object str >'
              ...:

          In [69]: f = Foo()

          In [70]: print(f)
          < Custom Foo object str >


          __getitem__、__setitem__、__delitem__

          用于索引操作,如字典。以上分別表示獲取、設(shè)置、刪除數(shù)據(jù)。

          用于切片操作,如列表。


          字典示例

          # __getitem__、__setitem__、__delitem__
          class MyDict(object):

              def __init__(self):
                  self.my_dict = dict()

              def __getitem__(self, key):
                  print('__getitem__() ', key)
                  return self.my_dict.get(key, None)

              def __setitem__(self, key, value):
                  print('__setitem__() ', key, value)
                  self.my_dict.update(key=value)

              def __delitem__(self, key):
                  print('__delitem__() ', key)
                  del self.my_dict[key]


          # ipython 測(cè)驗(yàn)        
          In [33]: mdict = MyDict()

          In [34]: print(mdict['name'])
          __getitem__()  name
          None

          In [35]: # 新增

          In [36]: mdict['name'] = 'hui'
          __setitem__()  name hui

          In [37]: mdict['age'] = 21
          __setitem__()  age 21

          In [38]: mdict['name']
          __getitem__()  name
          Out[38]: 'hui'

          In [39]: mdict['age']
          __getitem__()  age
          Out[39]: 21

          In [40]: # 更新

          In [41]: mdict['name'] = 'jack'
          __setitem__()  name jack

          In [42]: mdict['name']
          __getitem__()  name
          Out[42]: 'jack'

          In [43]: # 刪除

          In [44]: del mdict['age']
          __delitem__()  age

          In [45]: print(mdict['age'])
          __getitem__()  age
          None


          列表示例

          # 切片操作
          class MyList(object):

              def __init__(self):
                  self.mlist = list()

              def __getitem__(self, index):
                  print('__getitem__() called')
                  print(index)
                  if isinstance(index, slice):
                      return self.mlist[index]

              def __setitem__(self, index, value):
                  print('__getitem__() called')
                  print(index, value)
                  if isinstance(index, slice):
                      self.mlist[index] = value

              def __delitem__(self, index):
                  print('__delitem__() called')
                  if isinstance(index, slice):
                      del self.mlist[index]
               
              
          # ipython 測(cè)驗(yàn)
          In [70]: mlist = MyList()

          In [71]: mlist[0]
          __getitem__() called
          0

          In [72]: mlist[0:-1]
          __getitem__() called
          slice(0-1None)
          Out[72]: []

          In [73]: mlist[:] = [1,2,3]
          __getitem__() called
          slice(NoneNoneNone) [123]

          In [74]: mlist[:]
          __getitem__() called
          slice(NoneNoneNone)
          Out[74]: [123]

          In [75]: mlist[0:2]
          __getitem__() called
          slice(02None)
          Out[75]: [12]

          In [76]: mlist[::-1]
          __getitem__() called
          slice(NoneNone-1)
          Out[76]: [321]

          In [77]: mlist[0]
          __getitem__() called
          0

          In [78]: mlist[0:1]
          __getitem__() called
          slice(01None)
          Out[78]: [1]

          In [79]: del mlist[0:1]
          __delitem__() called

          In [80]: mlist[:]
          __getitem__() called
          slice(NoneNoneNone)
          Out[80]: [23]

          注意: 當(dāng)進(jìn)行 mlist[0] 操作的時(shí)候傳遞并不是一個(gè) slice 對(duì)象,不是一個(gè) int 類型的數(shù)字,所以不能把索引為 0 的值取出來(lái),改成 mlist[0, 1] 或者在 __getitem__() 的方法中新增數(shù)字判斷,大家可以嘗試一下。


          __enter__、__exit__

          with 聲明是從 Python2.5 開(kāi)始引進(jìn)的關(guān)鍵詞。你應(yīng)該遇過(guò)這樣子的代碼:

          with open('foo.txt'as bar:
              # do something with bar
              pass

          with 聲明的代碼段中,我們可以做一些對(duì)象的開(kāi)始操作和退出操作,還能對(duì)異常進(jìn)行處理。這需要實(shí)現(xiàn)兩個(gè)魔術(shù)方法: __enter__ 和 __exit__。

          __enter__(self):

          定義了當(dāng)使用 with 語(yǔ)句的時(shí)候,會(huì)話管理器在塊被初始創(chuàng)建時(shí)要產(chǎn)生的行為。請(qǐng)注意,__enter__ 的返回值與 with 語(yǔ)句的目標(biāo)或者 as 后的名字綁定。

          __exit__(self, exception_type, exception_value, traceback):

          定義了當(dāng)一個(gè)代碼塊被執(zhí)行或者終止后,會(huì)話管理器應(yīng)該做什么。它可以被用來(lái)處理異常、執(zhí)行清理工作或做一些代碼塊執(zhí)行完畢之后的日常工作。如果代碼塊執(zhí)行成功,exception_type,exception_value,和traceback 將會(huì)為 None 。否則,你可以選擇處理這個(gè)異常或者是直接交給用戶處理。如果你想處理這個(gè)異常的話,請(qǐng)確保__exit__ 在所有語(yǔ)句結(jié)束之后返回 True。如果你想讓異常被會(huì)話管理器處理的話,那么就讓其產(chǎn)生該異常。


          __copy__、__deepcopy__

          有時(shí)候,尤其是當(dāng)你在處理可變對(duì)象時(shí),你可能想要復(fù)制一個(gè)對(duì)象,然后對(duì)其做出一些改變而不希望影響原來(lái)的對(duì)象。這就是Python的copy所發(fā)揮作用的地方。

          __copy__(self):

          定義了當(dāng)對(duì)你的類的實(shí)例調(diào)用 copy.copy() 時(shí)所產(chǎn)生的行為。copy.copy() 返回了你的對(duì)象的一個(gè)淺拷貝——這意味著,當(dāng)實(shí)例本身是一個(gè)新實(shí)例時(shí),它的所有數(shù)據(jù)都被引用了——例如,當(dāng)一個(gè)對(duì)象本身被復(fù)制了,它的數(shù)據(jù)仍然是被引用的(因此,對(duì)于淺拷貝中數(shù)據(jù)的更改仍然可能導(dǎo)致數(shù)據(jù)在原始對(duì)象的中的改變)。

          __deepcopy__(self, memodict={}):

          定義了當(dāng)對(duì)你的類的實(shí)例調(diào)用 copy.deepcopy()時(shí)所產(chǎn)生的行為。copy.deepcopy() 返回了你的對(duì)象的一個(gè)深拷貝——對(duì)象和其數(shù)據(jù)都被拷貝了。memodict 是對(duì)之前被拷貝的對(duì)象的一個(gè)緩存——這優(yōu)化了拷貝過(guò)程并且阻止了對(duì)遞歸數(shù)據(jù)結(jié)構(gòu)拷貝時(shí)的無(wú)限遞歸。當(dāng)你想要進(jìn)行對(duì)一個(gè)單獨(dú)的屬性進(jìn)行深拷貝時(shí),調(diào)用copy.deepcopy(),并以 memodict 為第一個(gè)參數(shù)。


          這些魔術(shù)方法的用例看起來(lái)很小,并且確實(shí)非常實(shí)用. 它們反應(yīng)了關(guān)于面向?qū)ο蟪绦蛏弦恍┲匾臇|西在Python 上,并且總的來(lái)說(shuō) Python 總是一個(gè)簡(jiǎn)單的方法去找某些事情,即使是沒(méi)有必要的。這些魔法方法可能看起來(lái)不是很有用,但是一旦你需要它們,你會(huì)感到慶幸它們的存在。


          其他魔法方法

          由于魔法屬性、方法太多了在這就不一一描述和展示了,其他的就以表格形式呈現(xiàn)吧。

          用于比較的魔術(shù)方法

          方法作用
          __cmp__(self, other)比較方法里面最基本的的魔法方法
          __eq__(self, other)定義相等符號(hào)的行為,==
          __ne__(self,other)定義不等符號(hào)的行為,!=
          __lt__(self,other)定義小于符號(hào)的行為,<
          __gt__(self,other)定義大于符號(hào)的行為,>
          __le__(self,other)定義小于等于符號(hào)的行為,<=
          __ge__(self,other)定義大于等于符號(hào)的行為,>=

          數(shù)值計(jì)算的魔術(shù)方法

          單目運(yùn)算符和函數(shù)

          方法作用
          __pos__(self)實(shí)現(xiàn)一個(gè)取正數(shù)的操作
          __neg__(self)實(shí)現(xiàn)一個(gè)取負(fù)數(shù)的操作
          __abs__(self)實(shí)現(xiàn)一個(gè)內(nèi)建的 abs() 函數(shù)的行為
          __invert__(self)實(shí)現(xiàn)一個(gè)取反操作符(~操作符)的行為
          __round__(self, n)實(shí)現(xiàn)一個(gè)內(nèi)建的 round() 函數(shù)的行為
          __floor__(self)實(shí)現(xiàn) math.floor() 的函數(shù)行為
          __ceil__(self)實(shí)現(xiàn) math.ceil() 的函數(shù)行為
          __trunc__(self)實(shí)現(xiàn) math.trunc() 的函數(shù)行為

          雙目運(yùn)算符或函數(shù)

          方法作用
          __add__(self, other)實(shí)現(xiàn)一個(gè)加法
          __sub__(self, other)實(shí)現(xiàn)一個(gè)減法
          __mul__(self, other)實(shí)現(xiàn)一個(gè)乘法
          __floordiv__(self, other)實(shí)現(xiàn)一個(gè) // 操作符產(chǎn)生的整除操作
          __div__(self, other)實(shí)現(xiàn)一個(gè) / 操作符代表的除法操作
          __truediv__(self, other)實(shí)現(xiàn)真實(shí)除法
          __mod__(self, other)實(shí)現(xiàn)一個(gè) % 操作符代表的取模操作
          __divmod__(self, other)實(shí)現(xiàn)一個(gè)內(nèi)建函數(shù) divmod()
          __pow__(self, other)實(shí)現(xiàn)一個(gè)指數(shù)操作( ****** 操作符)的行為
          __lshift__(self, other)實(shí)現(xiàn)一個(gè)位左移操作**(<<)**的功能
          __rshift__(self, other)實(shí)現(xiàn)一個(gè)位右移操作**(>>)**的功能
          __and__(self, other)實(shí)現(xiàn)一個(gè)按位進(jìn)行與操作**(&)**的行為
          __or__(self, other)實(shí)現(xiàn)一個(gè)按位進(jìn)行或操作的行為
          __xor__(self, other)異或運(yùn)算符相當(dāng)于 ^

          增量運(yùn)算

          方法作用
          __iadd__(self, other)加法賦值
          __isub__(self, other)減法賦值
          __imul__(self, other)乘法賦值
          __ifloordiv__(self, other)整除賦值,地板除,相當(dāng)于 //= 運(yùn)算符
          __idiv__(self, other)除法賦值,相當(dāng)于 /= 運(yùn)算符
          __itruediv__(self, other)真除賦值
          __imod_(self, other)模賦值,相當(dāng)于 %= 運(yùn)算符
          __ipow__(self, other)乘方賦值,相當(dāng)于  **=  運(yùn)算符
          __ilshift__(self, other)左移賦值,相當(dāng)于 <<= 運(yùn)算符
          __irshift__(self, other)左移賦值,相當(dāng)于 >>= 運(yùn)算符
          __iand__(self, other)與賦值,相當(dāng)于 &= 運(yùn)算符
          __ior__(self, other)或賦值
          __ixor__(self, other)異或運(yùn)算符,相當(dāng)于 ^= 運(yùn)算符

          類型轉(zhuǎn)換

          方法作用
          __int__(self)轉(zhuǎn)換成整型
          __long__(self)轉(zhuǎn)換成長(zhǎng)整型
          __float__(self)轉(zhuǎn)換成浮點(diǎn)型
          __complex__(self)轉(zhuǎn)換成 復(fù)數(shù)型
          __oct__(self)轉(zhuǎn)換成八進(jìn)制
          __hex__(self)轉(zhuǎn)換成十六進(jìn)制
          __index__(self)如果你定義了一個(gè)可能被用來(lái)做切片操作的數(shù)值型,你就應(yīng)該定義__index__
          __trunc__(self)當(dāng) math.trunc(self)  使用時(shí)被調(diào)用 __trunc__ 返回自身類型的整型截取
          __coerce__(self, other)執(zhí)行混合類型的運(yùn)算

          大自然用數(shù)百億年創(chuàng)造出我們現(xiàn)實(shí)世界,而程序員用幾百年創(chuàng)造出一個(gè)完全不同的虛擬世界。我們用鍵盤敲出一磚一瓦,用大腦構(gòu)建一切。人們把1000視為權(quán)威,我們反其道行之,捍衛(wèi)1024的地位。我們不是鍵盤俠,我們只是平凡世界中不凡的締造者 。

          推薦閱讀
          誤執(zhí)行了rm -fr /*之后,除了跑路還能怎么辦?!
          程序員必備58個(gè)網(wǎng)站匯總
          大幅提高生產(chǎn)力:你需要了解的十大Jupyter Lab插件

          瀏覽 50
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷五月天激情小说 | 一起操91| 国产毛片成人网站 | 18 无码 高潮 蜜臀 | 色婷婷,大香蕉 |