成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

SICP Python 描述 2.2 數(shù)據(jù)抽象

Joonas / 3240人閱讀

摘要:示例有理數(shù)的算術(shù)有理數(shù)可表示為整數(shù)的比值,并且它組成了實(shí)數(shù)的一個(gè)重要子類(lèi)。有理數(shù)的值需要兩部分來(lái)描述。這里的重要概念是,通過(guò)將有理數(shù)表示為整數(shù)的比值,我們能夠完全避免近似問(wèn)題。返回有理數(shù)的分子。

2.2 數(shù)據(jù)抽象

來(lái)源:2.2 Data Abstraction

譯者:飛龍

協(xié)議:CC BY-NC-SA 4.0

由于我們希望在程序中表達(dá)世界中的大量事物,我們發(fā)現(xiàn)它們的大多數(shù)都具有復(fù)合結(jié)構(gòu)。日期是年月日,地理位置是精度和緯度。為了表示位置,我們希望程序語(yǔ)言具有將精度和緯度“粘合”為一對(duì)數(shù)據(jù)的能力 -- 也就是一個(gè)復(fù)合數(shù)據(jù)結(jié)構(gòu) -- 使我們的程序能夠以一種方式操作數(shù)據(jù),將位置看做單個(gè)概念單元,它擁有兩個(gè)部分。

復(fù)合數(shù)據(jù)的使用也讓我們?cè)黾映绦虻哪K性。如果我們可以直接將地理位置看做對(duì)象來(lái)操作,我們就可以將程序的各個(gè)部分分離,它們根據(jù)這些值如何表示來(lái)從本質(zhì)上處理這些值。將某個(gè)部分從程序中分離的一般技巧是一種叫做數(shù)據(jù)抽象的強(qiáng)大的設(shè)計(jì)方法論。這個(gè)部分用于處理數(shù)據(jù)表示,而程序用于操作數(shù)據(jù)。數(shù)據(jù)抽象使程序更易于設(shè)計(jì)、維護(hù)和修改。

數(shù)據(jù)抽象的特征類(lèi)似于函數(shù)抽象。當(dāng)我們創(chuàng)建函數(shù)抽象時(shí),函數(shù)如何實(shí)現(xiàn)的細(xì)節(jié)被隱藏了,而且特定的函數(shù)本身可以被任何具有相同行為的函數(shù)替換。換句話(huà)說(shuō),我們可以構(gòu)造抽象來(lái)使函數(shù)的使用方式和函數(shù)的實(shí)現(xiàn)細(xì)節(jié)分離。與之相似,數(shù)據(jù)抽象是一種方法論,使我們將復(fù)合數(shù)據(jù)對(duì)象的使用細(xì)節(jié)與它的構(gòu)造方式隔離。

數(shù)據(jù)抽象的基本概念是構(gòu)造操作抽象數(shù)據(jù)的程序。也就是說(shuō),我們的程序應(yīng)該以一種方式來(lái)使用數(shù)據(jù),對(duì)數(shù)據(jù)做出盡可能少的假設(shè)。同時(shí),需要定義具體的數(shù)據(jù)表示,獨(dú)立于使用數(shù)據(jù)的程序。我們系統(tǒng)中這兩部分的接口是一系列函數(shù),叫做選擇器和構(gòu)造器,它們基于具體表示實(shí)現(xiàn)了抽象數(shù)據(jù)。為了演示這個(gè)技巧,我們需要考慮如何設(shè)計(jì)一系列函數(shù)來(lái)操作有理數(shù)。

當(dāng)你閱讀下一節(jié)時(shí),要記住當(dāng)今編寫(xiě)的多數(shù) Python 代碼使用了非常高級(jí)的抽象數(shù)據(jù)類(lèi)型,它們內(nèi)建于語(yǔ)言中,比如類(lèi)、字典和列表。由于我們正在了解這些抽象的工作原理,我們自己不能使用它們。所以,我們會(huì)編寫(xiě)一些不那么 Python 化的代碼 -- 它并不是在語(yǔ)言中實(shí)現(xiàn)我們的概念的通常方式。但是,我們所編寫(xiě)的代碼出于教育目的,它展示了這些抽象如何構(gòu)建。要記住計(jì)算機(jī)科學(xué)并不只是學(xué)習(xí)如何使用編程語(yǔ)言,也學(xué)習(xí)它們的工作原理。

2.2.1 示例:有理數(shù)的算術(shù)

有理數(shù)可表示為整數(shù)的比值,并且它組成了實(shí)數(shù)的一個(gè)重要子類(lèi)。類(lèi)似于1/3或者17/29的有理數(shù)通??删帉?xiě)為:

/

其中,都是值為整數(shù)的占位符。有理數(shù)的值需要兩部分來(lái)描述。

有理數(shù)在計(jì)算機(jī)科學(xué)中很重要,因?yàn)樗鼈兙拖裾麛?shù)那樣,可以準(zhǔn)確表示。無(wú)理數(shù)(比如pi 或者 e 或者 sqrt(2))會(huì)使用有限的二元展開(kāi)代替為近似值。所以在原則上,有理數(shù)的處理應(yīng)該讓我們避免算術(shù)中的近似誤差。

但是,一旦我們真正將分子與分母相除,我們就會(huì)只剩下截?cái)嗟男?shù)近似值:

>>> 1/3
0.3333333333333333

當(dāng)我們開(kāi)始執(zhí)行測(cè)試時(shí),這個(gè)近似值的問(wèn)題就會(huì)出現(xiàn):

>>> 1/3 == 0.333333333333333300000  # Beware of approximations
True

計(jì)算機(jī)如何將實(shí)數(shù)近似為定長(zhǎng)的小數(shù)擴(kuò)展,是另一門(mén)課的話(huà)題。這里的重要概念是,通過(guò)將有理數(shù)表示為整數(shù)的比值,我們能夠完全避免近似問(wèn)題。所以出于精確,我們希望將分子和分母分離,但是將它們看做一個(gè)單元。

我們從函數(shù)抽象中了解到,我們可以在了解某些部分的實(shí)現(xiàn)之前開(kāi)始編出東西來(lái)。讓我們一開(kāi)始假設(shè)我們已經(jīng)擁有一種從分子和分母中構(gòu)造有理數(shù)的方式。我們也假設(shè),給定一個(gè)有理數(shù),我們都有辦法來(lái)提取(或選中)它的分子和分母。讓我們進(jìn)一步假設(shè),構(gòu)造器和選擇器以下面三個(gè)函數(shù)來(lái)提供:

make_rat(n, d)返回分子為n和分母為d的有理數(shù)。

numer(x)返回有理數(shù)x的分子。

denom(x)返回有理數(shù)x的分母。

我們?cè)谶@里正在使用一個(gè)強(qiáng)大的合成策略:心想事成。我們并沒(méi)有說(shuō)有理數(shù)如何表示,或者numerdenommake_rat如何實(shí)現(xiàn)。即使這樣,如果我們擁有了這三個(gè)函數(shù),我們就可以執(zhí)行加法、乘法,以及測(cè)試有理數(shù)的相等性,通過(guò)調(diào)用它們:

>>> def add_rat(x, y):
        nx, dx = numer(x), denom(x)
        ny, dy = numer(y), denom(y)
        return make_rat(nx * dy + ny * dx, dx * dy)
>>> def mul_rat(x, y):
        return make_rat(numer(x) * numer(y), denom(x) * denom(y))
>>> def eq_rat(x, y):
        return numer(x) * denom(y) == numer(y) * denom(x)

現(xiàn)在我們擁有了由選擇器函數(shù)numerdenom,以及構(gòu)造器函數(shù)make_rat定義的有理數(shù)操作。但是我們還沒(méi)有定義這些函數(shù)。我們需要以某種方式來(lái)將分子和分母粘合為一個(gè)單元。

2.2.2 元組

為了實(shí)現(xiàn)我們的數(shù)據(jù)抽象的具體層面,Python 提供了一種復(fù)合數(shù)據(jù)結(jié)構(gòu)叫做tuple,它可以由逗號(hào)分隔的值來(lái)構(gòu)造。雖然并不是嚴(yán)格要求,圓括號(hào)通常在元組周?chē)?/p>

>>> (1, 2)
(1, 2)

元組的元素可以由兩種方式解構(gòu)。第一種是我們熟悉的多重賦值:

>>> pair = (1, 2)
>>> pair
(1, 2)
>>> x, y = pair
>>> x
1
>>> y
2

實(shí)際上,多重賦值的本質(zhì)是創(chuàng)建和解構(gòu)元組。

訪(fǎng)問(wèn)元組元素的第二種方式是通過(guò)下標(biāo)運(yùn)算符,寫(xiě)作方括號(hào):

>>> pair[0]
1
>>> pair[1]
2

Python 中的元組(以及多數(shù)其它編程語(yǔ)言中的序列)下標(biāo)都以 0 開(kāi)始,也就是說(shuō),下標(biāo) 0 表示第一個(gè)元素,下標(biāo) 1 表示第二個(gè)元素,以此類(lèi)推。我們對(duì)這個(gè)下標(biāo)慣例的直覺(jué)是,下標(biāo)表示一個(gè)元素距離元組開(kāi)頭有多遠(yuǎn)。

與元素選擇操作等價(jià)的函數(shù)叫做getitem,它也使用下標(biāo)以 0 開(kāi)始的位置來(lái)在元組中選擇元素。

元素是原始類(lèi)型,也就是說(shuō) Python 的內(nèi)建運(yùn)算符可以操作它們。我們不久之后再來(lái)看元素的完整特性?,F(xiàn)在,我們只對(duì)元組如何作為膠水來(lái)實(shí)現(xiàn)抽象數(shù)據(jù)類(lèi)型感興趣。

表示有理數(shù)。元素提供了一個(gè)自然的方式來(lái)將有理數(shù)實(shí)現(xiàn)為一對(duì)整數(shù):分子和分母。我們可以通過(guò)操作二元組來(lái)實(shí)現(xiàn)我們的有理數(shù)構(gòu)造器和選擇器函數(shù)。

>>> def make_rat(n, d):
        return (n, d)
>>> def numer(x):
        return getitem(x, 0)
>>> def denom(x):
        return getitem(x, 1)

用于打印有理數(shù)的函數(shù)完成了我們對(duì)抽象數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)。

>>> def str_rat(x):
        """Return a string "n/d" for numerator n and denominator d."""
        return "{0}/{1}".format(numer(x), denom(x))

將它與我們之前定義的算術(shù)運(yùn)算放在一起,我們可以使用我們定義的函數(shù)來(lái)操作有理數(shù)了。

>>> half = make_rat(1, 2)
>>> str_rat(half)
"1/2"
>>> third = make_rat(1, 3)
>>> str_rat(mul_rat(half, third))
"1/6"
>>> str_rat(add_rat(third, third))
"6/9"

就像最后的例子所展示的那樣,我們的有理數(shù)實(shí)現(xiàn)并沒(méi)有將有理數(shù)化為最簡(jiǎn)。我們可以通過(guò)修改make_rat來(lái)補(bǔ)救。如果我們擁有用于計(jì)算兩個(gè)整數(shù)的最大公約數(shù)的函數(shù),我們可以在構(gòu)造一對(duì)整數(shù)之前將分子和分母化為最簡(jiǎn)。這可以使用許多實(shí)用工具,例如 Python 庫(kù)中的現(xiàn)存函數(shù)。

>>> from fractions import gcd
>>> def make_rat(n, d):
        g = gcd(n, d)
        return (n//g, d//g)

雙斜杠運(yùn)算符//表示整數(shù)除法,它會(huì)向下取整除法結(jié)果的小數(shù)部分。由于我們知道g能整除nd,整數(shù)除法正好適用于這里。現(xiàn)在我們的

>>> str_rat(add_rat(third, third))
"2/3"

符合要求。這個(gè)修改只通過(guò)修改構(gòu)造器來(lái)完成,并沒(méi)有修改任何實(shí)現(xiàn)實(shí)際算術(shù)運(yùn)算的函數(shù)。

擴(kuò)展閱讀。上面的str_rat實(shí)現(xiàn)使用了格式化字符串,它包含了值的占位符。如何使用格式化字符串和format方法的細(xì)節(jié)請(qǐng)見(jiàn) Dive Into Python 3 的格式化字符串一節(jié)。

2.2.3 抽象界限

在以更多復(fù)合數(shù)據(jù)和數(shù)據(jù)抽象的例子繼續(xù)之前,讓我們思考一些由有理數(shù)示例產(chǎn)生的問(wèn)題。我們使用構(gòu)造器make_rat和選擇器numerdenom定義了操作。通常,數(shù)據(jù)抽象的底層概念是,基于某個(gè)值的類(lèi)型的操作如何表達(dá),為這個(gè)值的類(lèi)型確定一組基本的操作。之后使用這些操作來(lái)操作數(shù)據(jù)。

我們可以將有理數(shù)系統(tǒng)想象為一系列層級(jí)。

平行線(xiàn)表示隔離系統(tǒng)不同層級(jí)的界限。每一層上,界限分離了使用數(shù)據(jù)抽象的函數(shù)(上面)和實(shí)現(xiàn)數(shù)據(jù)抽象的函數(shù)(下面)。使用有理數(shù)的程序僅僅通過(guò)算術(shù)函數(shù)來(lái)操作它們:add_rat、mul_rateq_rat。相應(yīng)地,這些函數(shù)僅僅由構(gòu)造器和選擇器make_rat、numerand denom來(lái)實(shí)現(xiàn),它們本身由元組實(shí)現(xiàn)。元組如何實(shí)現(xiàn)的字節(jié)和其它層級(jí)沒(méi)有關(guān)系,只要元組支持選擇器和構(gòu)造器的實(shí)現(xiàn)。

每一層上,盒子中的函數(shù)強(qiáng)制劃分了抽象的邊界,因?yàn)樗鼈儍H僅依賴(lài)于上層的表現(xiàn)(通過(guò)使用)和底層的實(shí)現(xiàn)(通過(guò)定義)。這樣,抽象界限可以表現(xiàn)為一系列函數(shù)。

抽象界限具有許多好處。一個(gè)好處就是,它們使程序更易于維護(hù)和修改。很少的函數(shù)依賴(lài)于特定的表現(xiàn),當(dāng)一個(gè)人希望修改表現(xiàn)時(shí),不需要做很多修改。

2.2.4 數(shù)據(jù)屬性

我們通過(guò)實(shí)現(xiàn)算術(shù)運(yùn)算來(lái)開(kāi)始實(shí)現(xiàn)有理數(shù),實(shí)現(xiàn)為這三個(gè)非特定函數(shù):make_ratnumerdenom。這里,我們可以認(rèn)為已經(jīng)定義了數(shù)據(jù)對(duì)象 -- 分子、分母和有理數(shù) -- 上的運(yùn)算,它們的行為由這三個(gè)函數(shù)規(guī)定。

但是數(shù)據(jù)意味著什么?我們還不能說(shuō)“提供的選擇器和構(gòu)造器實(shí)現(xiàn)了任何東西”。我們需要保證這些函數(shù)一起規(guī)定了正確的行為。也就是說(shuō),如果我們從整數(shù)nd中構(gòu)造了有理數(shù)x,那么numer(x)/denom(x)應(yīng)該等于n/d。

通常,我們可以將抽象數(shù)據(jù)類(lèi)型當(dāng)做一些選擇器和構(gòu)造器的集合,并帶有一些行為條件。只要滿(mǎn)足了行為條件(比如上面的除法特性),這些函數(shù)就組成了數(shù)據(jù)類(lèi)型的有效表示。

這個(gè)觀點(diǎn)可以用在其他數(shù)據(jù)類(lèi)型上,例如我們?yōu)閷?shí)現(xiàn)有理數(shù)而使用的二元組。我們實(shí)際上不會(huì)談?wù)撛M是什么,而是談?wù)撚烧Z(yǔ)言提供的,用于操作和創(chuàng)建元組的運(yùn)算符。我們現(xiàn)在可以描述二元組的行為條件,二元組通常叫做偶對(duì),在表示有理數(shù)的問(wèn)題中有所涉及。

為了實(shí)現(xiàn)有理數(shù),我們需要一種兩個(gè)整數(shù)的粘合形式,它具有下列行為:

如果一個(gè)偶對(duì)pxy構(gòu)造,那么getitem_pair(p, 0)返回x,getitem_pair(p, 1)返回y。

我們可以實(shí)現(xiàn)make_pairgetitem_pair,它們和元組一樣滿(mǎn)足這個(gè)描述:

>>> def make_pair(x, y):
        """Return a function that behaves like a pair."""
        def dispatch(m):
            if m == 0:
                return x
            elif m == 1:
                return y
        return dispatch
>>> def getitem_pair(p, i):
        """Return the element at index i of pair p."""
        return p(i)

使用這個(gè)實(shí)現(xiàn),我們可以創(chuàng)建和操作偶對(duì):

>>> p = make_pair(1, 2)
>>> getitem_pair(p, 0)
1
>>> getitem_pair(p, 1)
2

這個(gè)函數(shù)的用法不同于任何直觀上的,數(shù)據(jù)應(yīng)該是什么的概念。而且,這些函數(shù)滿(mǎn)足于在我們的程序中表示復(fù)合數(shù)據(jù)。

需要注意的微妙的一點(diǎn)是,由make_pair返回的值是叫做dispatch的函數(shù),它接受參數(shù)m并返回xy。之后,getitem_pair調(diào)用了這個(gè)函數(shù)來(lái)獲取合適的值。我們?cè)谶@一章中會(huì)多次返回拆解這個(gè)函數(shù)的話(huà)題。

這個(gè)偶對(duì)的函數(shù)表示并不是 Python 實(shí)際的工作機(jī)制(元組實(shí)現(xiàn)得更直接,出于性能因素),但是它可以以這種方式工作。這個(gè)函數(shù)表示雖然不是很明顯,但是是一種足夠完美來(lái)表示偶對(duì)的方式,因?yàn)樗鼭M(mǎn)足了偶對(duì)唯一需要滿(mǎn)足的條件。這個(gè)例子也表明,將函數(shù)當(dāng)做值來(lái)操作的能力,提供給我們表示復(fù)合數(shù)據(jù)的能力。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/45487.html

相關(guān)文章

  • SICP Python 描述 第二章 使用對(duì)象構(gòu)建抽象 2.1 引言

    摘要:對(duì)象表示信息,但是同時(shí)和它們所表示的抽象概念行為一致。通過(guò)綁定行為和信息,對(duì)象提供了可靠獨(dú)立的日期抽象。名稱(chēng)來(lái)源于實(shí)數(shù)在中表示的方式浮點(diǎn)表示。另一方面,對(duì)象可以表示很大范圍內(nèi)的分?jǐn)?shù),但是不能表示所有有理數(shù)。 2.1 引言 來(lái)源:2.1 Introduction 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 在第一章中,我們專(zhuān)注于計(jì)算過(guò)程,以及程序設(shè)計(jì)中函數(shù)的作用。我們看到了...

    phoenixsky 評(píng)論0 收藏0
  • SICP Python 描述 第三章 計(jì)算機(jī)程序的構(gòu)造和解釋 3.1 引言

    摘要:為通用語(yǔ)言設(shè)計(jì)解釋器的想法可能令人畏懼。但是,典型的解釋器擁有簡(jiǎn)潔的通用結(jié)構(gòu)兩個(gè)可變的遞歸函數(shù),第一個(gè)求解環(huán)境中的表達(dá)式,第二個(gè)在參數(shù)上調(diào)用函數(shù)。這一章接下來(lái)的兩節(jié)專(zhuān)注于遞歸函數(shù)和數(shù)據(jù)結(jié)構(gòu),它們是理解解釋器設(shè)計(jì)的基礎(chǔ)。 3.1 引言 來(lái)源:3.1 Introduction 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 第一章和第二章描述了編程的兩個(gè)基本元素:數(shù)據(jù)和函數(shù)之間的...

    v1 評(píng)論0 收藏0
  • SICP Python描述 1.1 引言

    摘要:另一個(gè)賦值語(yǔ)句將名稱(chēng)關(guān)聯(lián)到出現(xiàn)在莎士比亞劇本中的所有去重詞匯的集合,總計(jì)個(gè)。表達(dá)式是一個(gè)復(fù)合表達(dá)式,計(jì)算出正序或倒序出現(xiàn)的莎士比亞詞匯集合。在意圖上并沒(méi)有按照莎士比亞或者回文來(lái)設(shè)計(jì),但是它極大的靈活性讓我們用極少的代碼處理大量文本。 1.1 引言 來(lái)源:1.1 Introduction 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 計(jì)算機(jī)科學(xué)是一個(gè)極其寬泛的學(xué)科。全球的分布...

    xumenger 評(píng)論0 收藏0
  • SICP Python 描述 1.4 實(shí)踐指南:函數(shù)的藝術(shù)

    摘要:實(shí)踐指南函數(shù)的藝術(shù)來(lái)源譯者飛龍協(xié)議函數(shù)是所有程序的要素,無(wú)論規(guī)模大小,并且在編程語(yǔ)言中作為我們表達(dá)計(jì)算過(guò)程的主要媒介。目前為止,我們討論了函數(shù)的形式特性,以及它們?nèi)绾问褂?。第一行描述函?shù)的任務(wù)。 1.4 實(shí)踐指南:函數(shù)的藝術(shù) 來(lái)源:1.4 Practical Guidance: The Art of the Function 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 函...

    lemon 評(píng)論0 收藏0
  • SICP Python 描述 1.2 編程元素

    摘要:程序用于在編程社群的成員之間交流這些想法。在編程中,我們處理兩種元素函數(shù)和數(shù)據(jù)。在中,我們可以使用賦值語(yǔ)句來(lái)建立新的綁定,它包含左邊的名稱(chēng)和右邊的值。例如,它并不能處理賦值語(yǔ)句。這些圖解的必要部分是函數(shù)的表示。 1.2 編程元素 來(lái)源:1.2 The Elements of Programming 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 編程語(yǔ)言是操作計(jì)算機(jī)來(lái)執(zhí)行任務(wù)...

    CoorChice 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<