999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

Python的對象與型式

2017-09-28 19:02:08喬林
計算機教育 2017年9期

喬林

摘 要:作為動態語言,Python與其他靜態編譯語言有很大差別,其對象與型式的概念及關系非常讓人迷惑。文章討論Python程序設計語言中對象、型式與量的基本概念和關系,闡釋這些概念的內涵與外延,指出初學者容易混淆之處,并給出教學過程中的一點心得體會。

關鍵詞:Python;對象;型式;量

0 引 言

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

1 對象與型式

1.1 對 象

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

本征值是用于區分不同對象的信息,因而特征之一是應具有唯一性。在Python程序設計語言中,本征值的表示方式與Python程序設計語言的具體實現有關,一種典型的實現策略是使用對象在內存中的存儲地址,如CPython的實現。本征值的另外一個特征是有常性(immutability),即一經創設就不可改變。

在Python程序設計語言中,可以使用本征值函數id()返回某個特定對象的本征值,如在Cpython實現中,id(1)與id(obj)分別返回對象1與對象obj的本征值。相應地,也可以使用型式函數type()獲取某個對象的型式。

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

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

1.2 型 式

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

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

在面向對象技術出現之后,程序設計語言一般使用專用關鍵字來表示特定的將數據與操作辯證統一的數據結構——類,如C++程序設計語言中的關鍵字class(含擴充定義的struct)。在類中,對象屬性(attribute)和行為(behavior)被統一描述和管理:對象屬性是類的數據成員;對象行為是該類或該類的某個對象上可執行的操作成員,也稱為方法(method)。

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

Python程序設計語言作為一種純粹的面向對象語言,凡物皆為對象,這導致學生在學習時會面臨以下兩方面的困難。

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

(2)型也是可以在程序中操作的對象。可以認為,型就是構造對象的模板,然而在實際語言實現中,存在這樣一種情況,即一個對象本身實際上可以作為該型另外一個對象的模板。這意味著,型本身也可以作為對象來存儲和管理,并在程序運行過程中作為模板,用于構造該型的對象。因此,我們可以將程序編譯從靜態引向動態。

示例代碼一:

>>> id(int)

1707211232

>>> type(int)

>>> id(float)

1707205632

>>> type(float)

>>> int is float

False

# 試試將一個浮點型賦值給一個整型

>>> int = float

>>> id(int)

1707205632

>>> type(int)

>>> id(float)

1707205632

>>> type(float)

>>> int is float

True

>>>

1.3 型之相

在Python程序設計語言中,類具有明確的型。類的定義語句負責創建(構造)一個類型,而類型用于創建(構造)該類型的對象(object)。

構造類的一個實際對象的過程稱為具象化(instantiation),也稱為實例化。實例化的結果為具象(instance object),也稱實例對象。

實際上,在Python程序設計語言中,類定義結束時,系統將構造(創建)出該類的一個型象。如前所述,型亦為對象,因此,按照此型定義出的對象稱為對象(class object),也稱類象或類對象。

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

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

2 量與對象

2.1 文字與量

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

在Python程序設計語言中,量的處理相當特殊。事實上,它已經與C語言、C++語言等早期語言中的概念有了明顯差別。

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

這樣就引申出一個問題,即量的同一性(identity)問題——我們如何判斷兩個量是否引用了同一個對象。雖然Python程序設計語言提供兩個關鍵字(操作符)is和is not,用于測試量的同一性,但是實際問題是量的同一性依賴于Python程序設計語言的具體實現,如我們可以認定a = [] 與b = [] 總是引用不同的有常對象(空列表),a = b = [] 總是引用同一有常對象,卻并不能保證a = 1與b = 1是否引用了值為1的同一有常對象。

2.2 名空間與作用域

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

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

(1)標識符獨立性:不同名空間的同名標識符沒有任何關聯;

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

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

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

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

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

雖然作用域與名空間在概念上有強關聯,但是二者并不相同。一般認為,不在某名空間中,就不能訪問該名空間中的標識符;同時,在某名空間中,也不一定能訪問該名空間中的標識符。

在Python程序設計語言中,作用域分為局部作用域、外層函數閉包作用域、全局作用域和內置作用域這4類。其中,局部作用域位于最內層,為函數(類成員函數)、類或Lambda表達式形成的文法區域;外層函數閉包作用域為嵌套函數的外層函數形成的文法區域;全局作用域為模塊形成的文法區域;內置作用域位于最外層,為包含內置名稱的文法區域。

在進行標識符查找時,按照由內向外的順序查找上述4種作用域。

2.3 全局量與局部量

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

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

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

示例代碼二:

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

n = 42

# 形式參數x也為局部量,位于局部名空間,函數內部可訪問

def double(x):

# 訪問全局量n

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

# m為局部量,位于局部名空間,函數內部可訪問

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為全局量,位于全局名空間,與函數內部m為獨立的兩個對象

m = double(n)

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

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

示例代碼二的輸出結果如下:

# 調用函數前,全局量n值為42

Before calling double() in __main__: n = 42

# 調用函數中,全局量n值為42(加倍前)

Before being doubled in double(): n = 42

# 調用函數中,局部量m值為84(加倍后)

After being doubled in double(): m = 84

# 調用函數中,全局量n值為42(加倍后)

After being doubled in double(): n = 42

# 調用函數后,全局量m接受加倍值84

After calling double() in __main__: m = 84

# 調用函數后,全局量n值維持42不變

After calling double() in __main__: n = 42

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

示例代碼三如下:

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

n = 42

def double(x):

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

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

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

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

# 局部量n定義前雖不能訪問,但仍不允許上條注釋語句訪問全局量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 )

示例代碼三的輸出結果如下:

# 調用函數前,全局量n值為42

Before calling double() in __main__: n = 42

# 調用函數中,局部量n值為 42

After being doubled in double(): n = 84

# 調用函數中,全局量m接受加倍值84

After calling double() in __main__: m = 84

# 調用函數后,全局量n維持原值42不變

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

After calling double() in __main__: n = 42

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

再看示例代碼四:

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

n = 42

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

def double():

# 聲明全局量n,函數內部對其賦值不會構造新的局部對象

global n

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

# 直接寫入全局量,而不是構造新的局部對象

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 )

示例代碼四的輸出結果如下:

# 調用函數前,全局量n值為42

Before calling double() in __main__: n = 42

# 調用函數中,全局量n值為 42(加倍前)

Before being doubled in double(): n = 42

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

After being doubled in double(): n = 84

# 調用函數后,全局量m接受加倍值84

After calling double() in __main__: m = 84

# 調用函數后,全局量n維持更新后的值84不變

After calling double() in __main__: n = 84

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

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

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

3 結 語

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

主站蜘蛛池模板: 成人一区在线| a毛片在线免费观看| 日韩在线影院| 中文字幕啪啪| 日本不卡在线播放| 色欲色欲久久综合网| 999精品在线视频| 亚洲综合久久一本伊一区| 免费人成在线观看成人片| 精品无码日韩国产不卡av | 欧洲高清无码在线| av大片在线无码免费| 久久综合九色综合97婷婷| 久久精品无码国产一区二区三区| 超碰aⅴ人人做人人爽欧美| 国内精自线i品一区202| 国产毛片不卡| 国产免费精彩视频| 囯产av无码片毛片一级| 欧美性爱精品一区二区三区| 伊人精品视频免费在线| 四虎永久在线精品影院| 国产毛片片精品天天看视频| 波多野结衣一级毛片| 午夜精品福利影院| 一本一道波多野结衣一区二区 | 国产欧美视频在线观看| 久久精品一卡日本电影| 精品无码一区二区在线观看| аv天堂最新中文在线| 色丁丁毛片在线观看| 黄色污网站在线观看| 久久国产亚洲偷自| 中文字幕佐山爱一区二区免费| 在线日韩一区二区| 青青草原国产免费av观看| 凹凸国产熟女精品视频| 91精品国产自产在线观看| 欧美不卡视频在线观看| 狠狠干综合| 99re热精品视频国产免费| 日韩不卡高清视频| 综1合AV在线播放| 91美女视频在线| 婷婷开心中文字幕| 国产精品va免费视频| 激情国产精品一区| 国产性爱网站| 国产91特黄特色A级毛片| 在线精品亚洲国产| 日韩中文字幕亚洲无线码| 国产精品福利导航| 91国内外精品自在线播放| 精品视频福利| 4虎影视国产在线观看精品| 中文无码精品a∨在线观看| 国产主播在线观看| 日本欧美中文字幕精品亚洲| 国产成人夜色91| 五月婷婷综合在线视频| 国产在线精品人成导航| 国产视频欧美| 国模在线视频一区二区三区| 欧美日韩国产在线观看一区二区三区 | 国产人成在线视频| 亚洲色图欧美在线| 精品国产一区91在线| 黄色网在线| 色有码无码视频| 欧美亚洲另类在线观看| 免费人欧美成又黄又爽的视频| 久久一本精品久久久ー99| 91丝袜在线观看| 免费午夜无码18禁无码影院| 欧美亚洲国产一区| 美女高潮全身流白浆福利区| 久久亚洲日本不卡一区二区| 午夜免费小视频| 中文字幕日韩视频欧美一区| 亚洲成A人V欧美综合天堂| 国产农村妇女精品一二区| 亚洲AⅤ波多系列中文字幕|