<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 數(shù)據(jù)模型

          共 3380字,需瀏覽 7分鐘

           ·

          2020-10-06 05:26

          一、如何理解數(shù)據(jù)模型?

          最近我在閱讀一本專門(mén)講述 Python 語(yǔ)言特性的書(shū)(本文部分內(nèi)容來(lái)自?Fluent Python?這本書(shū)),書(shū)中提到了數(shù)據(jù)模型這個(gè)詞,數(shù)據(jù)模型是不是我們經(jīng)常說(shuō)的數(shù)據(jù)類型?其實(shí)不是,數(shù)據(jù)模型是對(duì) Python 框架的描述,他規(guī)范了自身構(gòu)建模塊的接口,這些接口我們可以理解為是 Python 中的特殊方法,例如?__iter__、__len____del__?等。這些模塊包括但不限于序列、迭代器、函數(shù)、類和上下文管理器。假如我們?cè)谟懻?,擁有哪些方法和屬性的?duì)象可以稱為序列,實(shí)際上我們就是在討論序列的數(shù)據(jù)模型。

          Python 最好的品質(zhì)之一是一致性,當(dāng)你使用 Python 一段時(shí)間以后,你就會(huì)開(kāi)始理解 Python 語(yǔ)言,并且能正確的猜出對(duì)你來(lái)說(shuō)是全新的語(yǔ)言特性。

          如果你帶著其他編程語(yǔ)言的經(jīng)歷來(lái)使用 Python ,你可能為?len(object)?而不是object.len()?而感到好奇,在?Java?語(yǔ)言中常常使用?object.len()?這種方法取得對(duì)象的長(zhǎng)度。當(dāng)你進(jìn)一步的理解這種不適感背后的強(qiáng)大之處的時(shí)候,你會(huì)被 Python 的設(shè)計(jì)哲學(xué)所折服,這正是建立在 Python 數(shù)據(jù)模型之上的結(jié)果,Python 數(shù)據(jù)模型的 API ,為我們使用地道的 Python 特性構(gòu)建對(duì)象提供了工具,這正是我們常常說(shuō)的?Pythonic。

          不管在哪種框架下寫(xiě)程序,都會(huì)花費(fèi)大量的時(shí)間區(qū)實(shí)現(xiàn)那些會(huì)被框架本身調(diào)用的方法,Python 框架本身也不例外。當(dāng)你在使用?object[item]?的時(shí)候,背后實(shí)際上是調(diào)用了object.__getitem__?這個(gè)方法。這樣的好處的是什么,這樣我們就可以對(duì)自建的對(duì)象使用?[]運(yùn)算符,我們只需要在類當(dāng)中定義?__getitem__?方法即可。

          __getitem__?是 Python 的特殊方法之一,常見(jiàn)的特殊方法還有__len____iter__、__enter__、__call__?等

          這些特殊方法,能讓你自己的對(duì)象實(shí)現(xiàn)和支持以下的語(yǔ)言架構(gòu),并與之交互。

          • 迭代

          • 集合類

          • 屬性訪問(wèn)

          • 運(yùn)算符重載

          • 函數(shù)和方法的調(diào)用

          • 對(duì)象的創(chuàng)建和銷毀

          • 字符串表示形式和格式化

          • 上下文管理器

          二、實(shí)現(xiàn)自己的序列類

          數(shù)據(jù)模型提供了使用 Python 語(yǔ)言特性的來(lái)構(gòu)建對(duì)象的 API ,那么我們嘗試著實(shí)現(xiàn)自己的序列類。

          class?MyList(object):
          ????
          ????def?__init__(self,?):
          ????????self.items?=?[str(x)?for?x?in?range(10)]
          ????????self.len?=?10

          ????def?__getitem__(self,?item):
          ????????return?self.items[item]

          ????def?__len__(self):
          ????????return?self.len

          a?=?MyList()

          for?x?in?a:
          ????print(x)
          print('第一個(gè)元素',?a[0])
          print("長(zhǎng)度:",?len(a))

          我們自己定義的類支持迭代,支持切片,也支持len?方法,這其實(shí)就是實(shí)現(xiàn)了 Python 序列的協(xié)議(非正式接口),我們通過(guò)數(shù)據(jù)模型實(shí)現(xiàn)了自定義的序列,而非子類化內(nèi)置序列,這其實(shí)也是鴨子模型的一種語(yǔ)言,當(dāng)某個(gè)類的行為看起來(lái)像鴨子(這里指代序列),那么這個(gè)類就可以說(shuō)是序列。不在乎是通過(guò)子類化,還是序列協(xié)議實(shí)現(xiàn)的。

          我們已經(jīng)可以體會(huì)到通過(guò)使用特殊方法來(lái)利用 Python 數(shù)據(jù)模型的好處,作為你的類的用戶,不必去記住標(biāo)準(zhǔn)操作的各式名稱(“怎么得到長(zhǎng)度?” 是 .size() 還是 .length() 還是別的什么 ?)

          上面的實(shí)例中,MyList?類可以進(jìn)行迭代和切片,切片的功能是由?__getitem__?提供的,迭代的功能實(shí)際上是由?__iter__?提供的,它返回一個(gè)可迭代對(duì)象。但是?MyList?類中沒(méi)有__iter__?方法,這是怎么回事呢?

          因?yàn)槿绻麤](méi)有實(shí)現(xiàn)?__iter__?方法, 但是實(shí)現(xiàn)了__getitem__?方法, Python 會(huì)創(chuàng)建一個(gè)迭代器,嘗試按順序( 從索引 0 開(kāi)始)獲取元素。

          現(xiàn)在我們嘗試打印?a?對(duì)象

          class?MyList(object):
          ????
          ????def?__init__(self,?):
          ????????self.items?=?[str(x)?for?x?in?range(10)]
          ????????self.len?=?10

          ????def?__getitem__(self,?item):
          ????????return?self.items[item]

          ????def?__len__(self):
          ????????return?self.len

          a?=?MyList()
          print(a)
          >>?<__main__.MyList?object?at?0x0000015AEAFC95F8>

          結(jié)果是一串我們不在意的內(nèi)存地址,但是我們經(jīng)常發(fā)現(xiàn),一些 Python 內(nèi)置模塊,或者第三方的庫(kù),當(dāng)我們直接打印某個(gè)對(duì)象的時(shí)候,輸出的是我們可以看懂的信息,而不是這樣的內(nèi)存地址。

          其實(shí)這個(gè)是可以通過(guò)特殊方法?__str__?來(lái)實(shí)現(xiàn)的,它返回一個(gè)字符串,我們可以通過(guò)為MyList?類添加一個(gè)?__str__?特殊方法實(shí)現(xiàn)。

          class?MyList(object):

          ????def?__init__(self,?):
          ????????self.items?=?[str(x)?for?x?in?range(10)]
          ????????self.len?=?10

          ????def?__getitem__(self,?item):
          ????????return?self.items[item]

          ????def?__len__(self):
          ????????return?self.len

          ????def?__str__(self):
          ????????return?','.join(self.items)

          a?=?MyList()
          print(a)
          >>?0,1,2,3,4,5,6,7,8,9

          三、為什么 len 不是普通方法

          如果 x 是一個(gè)內(nèi)置類型的實(shí)例,那么 len(x)的速度會(huì)非常快。背后的原因是 CPython 會(huì)直接從一個(gè) C 結(jié)構(gòu)體里讀取對(duì)象的長(zhǎng)度,完全不會(huì)調(diào)用任何方法。獲取一個(gè)集合中元素的數(shù)量是一個(gè)很常見(jiàn)的操作,在 str、list、memoryview 等類型上,這個(gè)操作必須高效。換句話說(shuō),len 之所以不是一個(gè)普通方法,是為了讓 Python 自帶的數(shù)據(jù)結(jié)構(gòu)可以走后門(mén),abs 也是同理。但是多虧了它是特殊方法,我們也可以把 len 用于自定義數(shù)據(jù)類型。這種處理方式在保持內(nèi)置類型的效率和保證語(yǔ)言的一致性之間找到了一個(gè)平衡點(diǎn),也印證了“ Python 之 ”中的另外一句話:“不能讓特例特殊到開(kāi)始破壞既定規(guī)則?!?/p>

          四、數(shù)據(jù)模型與特殊方法

          數(shù)據(jù)模型描述的是對(duì)象協(xié)議,而特殊方法正是內(nèi)置對(duì)象的所實(shí)現(xiàn)的協(xié)議,為了讓我們的代碼風(fēng)格表現(xiàn)的和內(nèi)置類型一樣,或者說(shuō)更 Python 風(fēng)格的代碼,我們可以使用特殊方法,而不是子類化。

          對(duì)象的一個(gè)基本要求就是它得要有合理的字符串表示形式,我們可以通過(guò)?__str__?和__repr__?來(lái)滿足這個(gè)要求。__repr__?方便我們調(diào)試,__str__?適合給終端用戶看。這就是數(shù)據(jù)模型中存在特殊方法?__repr__?和?__str__?的原因。

          Python 中的特殊方法還有很多,這里主要講述的還是數(shù)據(jù)模型,希望大家可以理解 Python 語(yǔ)言的設(shè)計(jì)哲學(xué),以及思考如何寫(xiě)出更?Pythonic?的代碼。

          公眾號(hào)推薦:數(shù)據(jù)思踐

          數(shù)據(jù)思踐公眾號(hào)記錄和分享數(shù)據(jù)人思考和踐行的內(nèi)容與故事。

          《數(shù)據(jù)科學(xué)與人工智能》公眾號(hào)推薦朋友們學(xué)習(xí)和使用Python語(yǔ)言,需要加入Python語(yǔ)言群的,請(qǐng)掃碼加我個(gè)人微信,備注【姓名-Python群】,我誠(chéng)邀你入群,大家學(xué)習(xí)和分享。

          關(guān)于Python語(yǔ)言,有任何問(wèn)題或者想法,請(qǐng)留言或者加群討論。

          瀏覽 49
          點(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禁www|