• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

      Python的對象與型式

      2017-09-28 19:02:08喬林
      計(jì)算機(jī)教育 2017年9期
      關(guān)鍵詞:型式對象

      喬林

      摘 要:作為動(dòng)態(tài)語言,Python與其他靜態(tài)編譯語言有很大差別,其對象與型式的概念及關(guān)系非常讓人迷惑。文章討論P(yáng)ython程序設(shè)計(jì)語言中對象、型式與量的基本概念和關(guān)系,闡釋這些概念的內(nèi)涵與外延,指出初學(xué)者容易混淆之處,并給出教學(xué)過程中的一點(diǎn)心得體會(huì)。

      關(guān)鍵詞:Python;對象;型式;量

      0 引 言

      對于Python程序設(shè)計(jì)語言對象與型式的概念、關(guān)系等基本概念,如果沒有清晰的認(rèn)知,那么所編寫的Python程序(腳本)重者無法運(yùn)行或者得到錯(cuò)誤的結(jié)果,輕者可能隱含難以察覺和調(diào)試的邏輯錯(cuò)誤。因此,了解Python程序設(shè)計(jì)語言中對象、型式與量的基本概念和關(guān)系,掌握文字與量、名空間與作用域、全局量與局部量的概念以及這些基礎(chǔ)概念對量(對象)可能造成的影響至關(guān)重要。

      1 對象與型式

      1.1 對 象

      對象(object)是一種數(shù)據(jù)抽象或數(shù)據(jù)結(jié)構(gòu)抽象,用來表示程序中需要處理或已處理的信息。在Python程序設(shè)計(jì)語言中,對象具有3個(gè)基本特征:本征值(identity)、型式(type)和值(value)。

      本征值是用于區(qū)分不同對象的信息,因而特征之一是應(yīng)具有唯一性。在Python程序設(shè)計(jì)語言中,本征值的表示方式與Python程序設(shè)計(jì)語言的具體實(shí)現(xiàn)有關(guān),一種典型的實(shí)現(xiàn)策略是使用對象在內(nèi)存中的存儲(chǔ)地址,如CPython的實(shí)現(xiàn)。本征值的另外一個(gè)特征是有常性(immutability),即一經(jīng)創(chuàng)設(shè)就不可改變。

      在Python程序設(shè)計(jì)語言中,可以使用本征值函數(shù)id()返回某個(gè)特定對象的本征值,如在Cpython實(shí)現(xiàn)中,id(1)與id(obj)分別返回對象1與對象obj的本征值。相應(yīng)地,也可以使用型式函數(shù)type()獲取某個(gè)對象的型式。

      在Python程序設(shè)計(jì)語言中,依據(jù)該對象是否可被改變,而分為有常對象(immutable)和無常對象(mutable)。

      一般而言,Python程序設(shè)計(jì)語言中的對象無常性由其型式確定。典型的示例,如數(shù)值(numeric)、字符串(string)和元組(tuple)為有常對象,詞典(dictionary)和列表(list)為無常對象;此外,有常容器(container)對象可能包含無常元素對象,前者值不可變,后者則不然。對于這兩點(diǎn),初學(xué)者必須時(shí)刻保持警覺,教師在教學(xué)過程中也必須闡釋清楚。

      1.2 型 式

      型式(type),簡稱型,也稱類型。在純面向?qū)ο笳Z言出現(xiàn)之前,type用來表示相同性質(zhì)的數(shù)據(jù)集合。該集合雖然具有明確的操作集,厘定了可在該集合上實(shí)施的操作,但是并未在語言層面上對其進(jìn)行明晰的操作集定義,即數(shù)據(jù)及其操作是分離的。

      型,其最主要的目的是構(gòu)造該型式的對象。這意味著任何對象都必須有確切的型式,且一般不可改變。

      在面向?qū)ο蠹夹g(shù)出現(xiàn)之后,程序設(shè)計(jì)語言一般使用專用關(guān)鍵字來表示特定的將數(shù)據(jù)與操作辯證統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)——類,如C++程序設(shè)計(jì)語言中的關(guān)鍵字class(含擴(kuò)充定義的struct)。在類中,對象屬性(attribute)和行為(behavior)被統(tǒng)一描述和管理:對象屬性是類的數(shù)據(jù)成員;對象行為是該類或該類的某個(gè)對象上可執(zhí)行的操作成員,也稱為方法(method)。

      語言學(xué)上,class的翻譯為“類”,作為型(type)的一種,也可以稱為“類型”。這使得其與早期術(shù)語type之間,容易出現(xiàn)一定混淆——早期非class類型的type也被翻譯成“類型”。為避免引起誤解,將type更正為“型式”更佳,有助于區(qū)分class與type ——兩者在程序設(shè)計(jì)語言層面上并非同一概念。

      Python程序設(shè)計(jì)語言作為一種純粹的面向?qū)ο笳Z言,凡物皆為對象,這導(dǎo)致學(xué)生在學(xué)習(xí)時(shí)會(huì)面臨以下兩方面的困難。

      (1)class與type的本質(zhì)完全相同,類即為型,而型亦為類。此時(shí),討論其他編程語言中這兩者的差異,就沒有任何意義。因此,很多學(xué)習(xí)過其他面向?qū)ο笳Z言的學(xué)生在學(xué)習(xí)Python程序設(shè)計(jì)語言時(shí),反而會(huì)面臨概念理解上的困難。這一點(diǎn),授課教師必須在教學(xué)過程中表述清楚,以減少學(xué)生的困惑。

      (2)型也是可以在程序中操作的對象??梢哉J(rèn)為,型就是構(gòu)造對象的模板,然而在實(shí)際語言實(shí)現(xiàn)中,存在這樣一種情況,即一個(gè)對象本身實(shí)際上可以作為該型另外一個(gè)對象的模板。這意味著,型本身也可以作為對象來存儲(chǔ)和管理,并在程序運(yùn)行過程中作為模板,用于構(gòu)造該型的對象。因此,我們可以將程序編譯從靜態(tài)引向動(dòng)態(tài)。

      示例代碼一:

      >>> id(int)

      1707211232

      >>> type(int)

      >>> id(float)

      1707205632

      >>> type(float)

      >>> int is float

      False

      # 試試將一個(gè)浮點(diǎn)型賦值給一個(gè)整型

      >>> int = float

      >>> id(int)

      1707205632

      >>> type(int)

      >>> id(float)

      1707205632

      >>> type(float)

      >>> int is float

      True

      >>>

      1.3 型之相

      在Python程序設(shè)計(jì)語言中,類具有明確的型。類的定義語句負(fù)責(zé)創(chuàng)建(構(gòu)造)一個(gè)類型,而類型用于創(chuàng)建(構(gòu)造)該類型的對象(object)。

      構(gòu)造類的一個(gè)實(shí)際對象的過程稱為具象化(instantiation),也稱為實(shí)例化。實(shí)例化的結(jié)果為具象(instance object),也稱實(shí)例對象。

      實(shí)際上,在Python程序設(shè)計(jì)語言中,類定義結(jié)束時(shí),系統(tǒng)將構(gòu)造(創(chuàng)建)出該類的一個(gè)型象。如前所述,型亦為對象,因此,按照此型定義出的對象稱為對象(class object),也稱類象或類對象。

      對于初學(xué)者而言,這種概念上的差別非常容易讓人迷惑。類(型)本身就是構(gòu)造對象的模板,那么類對象或型對象是什么?在教學(xué)過程中,教師必須特別強(qiáng)調(diào)Python程序設(shè)計(jì)語言的類(型)動(dòng)態(tài)性,這一點(diǎn)與C語言和C++語言有很大的區(qū)別。因而,我們更傾向于將由類定義而創(chuàng)建(構(gòu)造)出來的類對象稱為型相,即使用“相”字區(qū)分實(shí)際對象的“象”字。

      也就是說,對于任意一個(gè)類,其類定義創(chuàng)建(構(gòu)造)了該類的一個(gè)型相;而通過該型相,程序員可以創(chuàng)建(構(gòu)造)該類的具象——具體的象。對于前者,構(gòu)造型相的過程,我們稱為體化(型體化);對于后者,構(gòu)造具象的過程被稱為具象化(象化)。體化的書面意義是指“以自己的行動(dòng)感化別人”,而“體”本身指“事物的本身或全部”“物質(zhì)存在的狀態(tài)或形狀”或“事物的格局、規(guī)矩”,因此用“體化”描述這個(gè)過程似乎更恰當(dāng)。

      2 量與對象

      2.1 文字與量

      文字(literal)是內(nèi)置類型的有常值,類似于數(shù)學(xué)或物理中的常數(shù),如0、3.1 416、2.718 28j、“Python”等。一方面,在Python程序設(shè)計(jì)語言中,文字亦對象;另一方面,量(variable)是引用特定對象的標(biāo)識符,類似數(shù)學(xué)中的代數(shù)。

      在Python程序設(shè)計(jì)語言中,量的處理相當(dāng)特殊。事實(shí)上,它已經(jīng)與C語言、C++語言等早期語言中的概念有了明顯差別。

      首先,量可以隨意引用數(shù)值、字符串或其他類型的對象;其次,量是標(biāo)識符(identifier),是名稱(name),但并不是該對象本身,僅僅是對“象”的引用(reference),即對該“對象”的“象”的引用;最后,對于Python程序設(shè)計(jì)語言中的量而言,賦值(assignment)即定義(definition),因而并不需要在使用量前作預(yù)先定義。這意味著賦值的目的并不是將賦值操作符右邊表達(dá)式的結(jié)果,存入該量所對應(yīng)的存儲(chǔ)空間,而是將代表該量的名稱(name)與賦值操作符右邊表達(dá)式的結(jié)果所對應(yīng)的值,束定(bind)或重新束定(rebind)在一起,以修改無常對象的屬性或值。

      這樣就引申出一個(gè)問題,即量的同一性(identity)問題——我們?nèi)绾闻袛鄡蓚€(gè)量是否引用了同一個(gè)對象。雖然Python程序設(shè)計(jì)語言提供兩個(gè)關(guān)鍵字(操作符)is和is not,用于測試量的同一性,但是實(shí)際問題是量的同一性依賴于Python程序設(shè)計(jì)語言的具體實(shí)現(xiàn),如我們可以認(rèn)定a = [] 與b = [] 總是引用不同的有常對象(空列表),a = b = [] 總是引用同一有常對象,卻并不能保證a = 1與b = 1是否引用了值為1的同一有常對象。

      2.2 名空間與作用域

      在概念上,名空間(namespace)是從名稱到對象的映射。在實(shí)現(xiàn)上,大多數(shù)名空間表現(xiàn)為符號表,以字典的形式來組織,而變量存儲(chǔ)其中。在Python腳本中存在多個(gè)相互獨(dú)立的名空間。

      一般而言,名空間具有如下特性:

      (1)標(biāo)識符獨(dú)立性:不同名空間的同名標(biāo)識符沒有任何關(guān)聯(lián);

      (2)標(biāo)識符唯一性:同一名空間中的標(biāo)識符不得重名;

      (3)名空間嵌套:一個(gè)名空間可以包含另外一個(gè)名空間。

      在Python程序設(shè)計(jì)語言中,名空間分為內(nèi)置名空間(built-in namespace)、全局名空間和局部名空間這3類。其中,內(nèi)置名空間為內(nèi)置名稱集合,如內(nèi)置函數(shù)名、內(nèi)置異常名等;全局名空間為模塊內(nèi)部的全局名稱集合;而局部名空間為函數(shù)調(diào)用時(shí)的本地名稱集合、對象的屬性集合、嵌套函數(shù)的本地名稱集合或類成員函數(shù)的本地名稱集合等。

      需要說明的是,全局名空間也稱模塊全局名空間,在讀入模塊定義時(shí)創(chuàng)建,且正常情況下在Python解釋器退出時(shí)刪除。此處所說的“全局”僅指在該模塊內(nèi)部為全局的。每個(gè)模塊都有獨(dú)立的全局名空間,導(dǎo)入模塊后方可訪問其中的全局標(biāo)識符;同時(shí),模塊中可能存在非全局標(biāo)識符,即使導(dǎo)入模塊也不可訪問,這一點(diǎn)是初學(xué)者很容易犯糊涂的地方,教師在教學(xué)時(shí)須予以重視。

      另一個(gè)相關(guān)的概念是作用域(scope)。定義上,作用域是指可訪問名空間中標(biāo)識符的文法區(qū)域,即在Python程序文本的某處,是否可以使用該名空間中的標(biāo)識符。

      雖然作用域與名空間在概念上有強(qiáng)關(guān)聯(lián),但是二者并不相同。一般認(rèn)為,不在某名空間中,就不能訪問該名空間中的標(biāo)識符;同時(shí),在某名空間中,也不一定能訪問該名空間中的標(biāo)識符。

      在Python程序設(shè)計(jì)語言中,作用域分為局部作用域、外層函數(shù)閉包作用域、全局作用域和內(nèi)置作用域這4類。其中,局部作用域位于最內(nèi)層,為函數(shù)(類成員函數(shù))、類或Lambda表達(dá)式形成的文法區(qū)域;外層函數(shù)閉包作用域?yàn)榍短缀瘮?shù)的外層函數(shù)形成的文法區(qū)域;全局作用域?yàn)槟K形成的文法區(qū)域;內(nèi)置作用域位于最外層,為包含內(nèi)置名稱的文法區(qū)域。

      在進(jìn)行標(biāo)識符查找時(shí),按照由內(nèi)向外的順序查找上述4種作用域。

      2.3 全局量與局部量

      一般將定義于類、函數(shù)、類成員函數(shù)或Lambda表達(dá)式之外場合的量稱為全局量;將定義于函數(shù)、類成員函數(shù)或Lambda表達(dá)式中的量稱為局部量。函數(shù)的形式參數(shù)與局部量類似,但是出于參數(shù)傳遞的原因,其與普通局部量有細(xì)微差異。

      需要說明的是,全局量與局部量位于不同的名空間,因而可重名;同時(shí),全局量和局部量重名時(shí),局部量可能遮蓋全局量的作用域,使其不可見。endprint

      在賦值即定義的原則下,Python程序設(shè)計(jì)語言中,全局量和局部量的差別經(jīng)常讓初學(xué)者迷惑,如以下3段代碼。

      示例代碼二:

      # n為全局量,位于全局名空間,其后代碼(包括函數(shù)內(nèi)部)均可訪問

      n = 42

      # 形式參數(shù)x也為局部量,位于局部名空間,函數(shù)內(nèi)部可訪問

      def double(x):

      # 訪問全局量n

      print( "Before being doubled in double(): n = ", n )

      # m為局部量,位于局部名空間,函數(shù)內(nèi)部可訪問

      m = x * 2

      print( "After being doubled in double(): m = ", m )

      print( "After being doubled in double(): n = ", n )

      return m

      print( "Before calling double() in __main__: n = ", n )

      # m為全局量,位于全局名空間,與函數(shù)內(nèi)部m為獨(dú)立的兩個(gè)對象

      m = double(n)

      print( "After calling double() in __main__: m = ", m )

      print( "After calling double() in __main__: n = ", n )

      示例代碼二的輸出結(jié)果如下:

      # 調(diào)用函數(shù)前,全局量n值為42

      Before calling double() in __main__: n = 42

      # 調(diào)用函數(shù)中,全局量n值為42(加倍前)

      Before being doubled in double(): n = 42

      # 調(diào)用函數(shù)中,局部量m值為84(加倍后)

      After being doubled in double(): m = 84

      # 調(diào)用函數(shù)中,全局量n值為42(加倍后)

      After being doubled in double(): n = 42

      # 調(diào)用函數(shù)后,全局量m接受加倍值84

      After calling double() in __main__: m = 84

      # 調(diào)用函數(shù)后,全局量n值維持42不變

      After calling double() in __main__: n = 42

      在示例代碼二中,n為全局量;m既可能為全局量,又可能為局部量,這與其所在的文法區(qū)域有關(guān),如函數(shù)內(nèi)部的m為局部量,函數(shù)定義之后使用的m為全局量。

      示例代碼三如下:

      # n為全局量,位于全局名空間,其后代碼(包括函數(shù)內(nèi)部)均可訪問

      n = 42

      def double(x):

      # 注釋下一條語句,否則無法束定局部量n,引發(fā)UnboundLocalError異常

      # print( "Before being doubled in double(): n = ", n )

      # 定義同名局部量n(賦值即定義),新對象具有局部作用域,整個(gè)函數(shù)內(nèi)部均有效

      # 局部量n遮蓋同名全局量n的部分作用域,使其不可見

      # 局部量n定義前雖不能訪問,但仍不允許上條注釋語句訪問全局量n

      # 換言之,即使前述被注釋的那條語句出現(xiàn)在局部量n定義之前,n也被解釋為局部量

      n = x * 2

      print( "After being doubled in double(): n = ", n )

      return n

      print( "Before calling double() in __main__: n = ", n )

      m = double(n)

      print( "After calling double() in __main__: m = ", m )

      print( "After calling double() in __main__: n = ", n )

      示例代碼三的輸出結(jié)果如下:

      # 調(diào)用函數(shù)前,全局量n值為42

      Before calling double() in __main__: n = 42

      # 調(diào)用函數(shù)中,局部量n值為 42

      After being doubled in double(): n = 84

      # 調(diào)用函數(shù)中,全局量m接受加倍值84

      After calling double() in __main__: m = 84

      # 調(diào)用函數(shù)后,全局量n維持原值42不變

      # 即全局量n與局部量n雖同名,但不是同一對象

      After calling double() in __main__: n = 42

      在示例代碼三中,視定義n時(shí)的文法區(qū)域,n可能為全局量,也可能為局部量;m則為全局量。相關(guān)代碼解釋已列入程序注釋,此處不再贅述。

      再看示例代碼四:

      # n為全局量,位于全局名空間,其后代碼(包括函數(shù)內(nèi)部)均可訪問

      n = 42

      # 直接使用全局量n,無需傳遞參數(shù)endprint

      def double():

      # 聲明全局量n,函數(shù)內(nèi)部對其賦值不會(huì)構(gòu)造新的局部對象

      global n

      print( "Before being doubled in double(): n = ", n )

      # 直接寫入全局量,而不是構(gòu)造新的局部對象

      n = n * 2

      print( "After being doubled in double(): n = ", n )

      return n

      print( "Before calling double() in __main__: n = ", n )

      m = double()

      print( "After calling double() in __main__: m = ", m )

      print( "After calling double() in __main__: n = ", n )

      示例代碼四的輸出結(jié)果如下:

      # 調(diào)用函數(shù)前,全局量n值為42

      Before calling double() in __main__: n = 42

      # 調(diào)用函數(shù)中,全局量n值為 42(加倍前)

      Before being doubled in double(): n = 42

      # 調(diào)用函數(shù)中,全局量n值更新為84(加倍后)

      After being doubled in double(): n = 84

      # 調(diào)用函數(shù)后,全局量m接受加倍值84

      After calling double() in __main__: m = 84

      # 調(diào)用函數(shù)后,全局量n維持更新后的值84不變

      After calling double() in __main__: n = 84

      由于賦值定義的特性,要在Python函數(shù)內(nèi)部修改全局量的值,就必須使用global將其聲明為全局量,原因是在函數(shù)內(nèi)部可以自由引用全局量,但不能對其賦值——賦值隱含著構(gòu)造新的同名局部對象。

      類似的關(guān)鍵字還有nonlocal,用于將其后標(biāo)識符解釋為非局部非全局的。查找標(biāo)識符時(shí),Python解釋器將從最內(nèi)層嵌套名空間向外查找,一直到全局名空間(不含);若未找到該標(biāo)識符,系統(tǒng)將引發(fā)SyntaxError異常。

      無論是global還是nonlocal,標(biāo)識符在其定義所在的代碼塊各處均有效,包括該聲明之前。

      3 結(jié) 語

      本文探討了Python程序設(shè)計(jì)語言中的對象、型式與量的基本概念和關(guān)系以及對象與型式的基本概念,指出了型相與具象的本質(zhì)及兩者之間的差異,并解釋了文字與量、名空間與作用域、全局量與局部量的概念,指出了這些基礎(chǔ)概念對量(對象)可能造成的影響。在實(shí)際編程時(shí),對這些概念的理解偏差極大地影響程序的健壯性和正確性,因而需要在教學(xué)過程中予以詳盡的說明。endprint

      猜你喜歡
      型式對象
      神秘來電
      睿士(2023年2期)2023-03-02 02:01:09
      幕墻型式對高層建筑室內(nèi)自然通風(fēng)影響的模擬
      煤氣與熱力(2021年9期)2021-11-06 05:22:48
      現(xiàn)代中小河流常用有壩壅水建筑物型式探討
      攻略對象的心思好難猜
      意林(2018年3期)2018-03-02 15:17:24
      軍持的型式分析與年代分期
      東方考古(2017年0期)2017-07-11 01:37:54
      基于熵的快速掃描法的FNEA初始對象的生成方法
      區(qū)間對象族的可鎮(zhèn)定性分析
      6-APA裂解過程攪拌型式的研究及改進(jìn)
      武邑县| 商都县| 壶关县| 辛集市| 大新县| 德保县| 罗田县| 武功县| 德兴市| 苏州市| 南乐县| 沈丘县| 扎囊县| 台北县| 沾益县| 隆德县| 平和县| 伊金霍洛旗| 夹江县| 武功县| 漳州市| 天峻县| 东丰县| 洞口县| 西宁市| 湖南省| 柘荣县| 卓资县| 柳江县| 且末县| 乐安县| 元谋县| 潢川县| 册亨县| 当阳市| 德江县| 通河县| 浪卡子县| 和政县| 云和县| 洪江市|