簡單類型
內(nèi)置到 Python 編程語言中的簡單數(shù)據(jù)類型包括:
bool
int
float
complex
支持簡單數(shù)據(jù)類型不是 Python 獨有的功能,因為多數(shù)現(xiàn)代編程語言都具有完整類型補充。例如 Java? 語言甚至有一組更豐富的原始數(shù)據(jù)類型:
byte
short
int
long
float
double
char
boolean
但是,在 Python 中,簡單數(shù)據(jù)類型并不是原始數(shù)據(jù)類型,而是完善的對象,它們有自已的方法和類。另外,這些簡單的內(nèi)置類型是不可改變的,這意味著:創(chuàng)建對象之后,您無法更改對象的值。如果需要新值,則必須創(chuàng)建新的對象。Python 簡單數(shù)據(jù)類型的不可改變特性與其他多數(shù)流行語言(如 Java 語言)處理簡單原始類型的方式不同。但是,當(dāng)您對這些簡單數(shù)據(jù)類型的對象屬性有了更多的了解之后,就很容易理解這種差異。
所以,整數(shù)如何能夠擁有一些方法?它僅僅是一個數(shù)字嗎?不是的,至少在 Python 中答案是否定的。您自已可以對它進行檢驗:僅借助內(nèi)置的 help 方法,就可以向 Python 解釋器咨詢關(guān)于 int 對象的信息(參見清單 1 )。
清單 1. Python 解釋器: 用于整數(shù)對象的 Help
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
rb % python Python 2.4 ( #1, Mar 29 2005, 12:05:39) [GCC 3.3 20030304ppp (Apple Computer, Inc. build 1495 )] on darwin Type "help" , "copyright" , "credits" or "license" for more information. >>> help ( int ) Help on class int in module __builtin__: class int ( object ) | int (x[, base]) - > integer | | Convert a string or number to an integer, if possible. A floating point | argument will be truncated towards zero (this does not include a string | representation of a floating point number!) When converting a string, use | the optional base. It is an error to supply a base when converting a | non - string. If the argument is outside the integer range a long object | will be returned instead. | | Methods defined here: | | __abs__(...) | x.__abs__() < = = > abs (x) | | __add__(...) | x.__add__(y) < = = > x + y ... |
這具體說明了什么?只有一個事情,那就是可以方便地從 Python 解釋器中得到幫助,但是從后面部分可以獲得更多幫助。第一行告訴您正在查看 int 類的幫助頁面,它是一個內(nèi)置的數(shù)據(jù)類型。如果您對面向?qū)ο蟮木幊痰母拍畈惶煜ぃ敲纯梢詫㈩?想像成只是一個用于構(gòu)建特殊事物并與之交互的藍圖。好比房子的設(shè)計藍圖,不僅顯示如何構(gòu)建房子,還顯示房子完工之后,如何更好地使用房子。例如,設(shè)計圖會顯示不同房間的位置、在房間之間的移動方式以及出入房子的通道情況。
第一行的下面是對實際 int 類的詳細說明。在這一點上,您可能不熟悉如何在 Python 中創(chuàng)建類,因為顯示的語法類似于外語。沒關(guān)系,我將在另一篇文章中對此進行全面介紹。現(xiàn)在,您只需要知道:int 對象是從 object 類中繼承而來,它是 Python 中許多內(nèi)容的一個基類。
后面的幾行介紹 int 類的構(gòu)造函數(shù)。構(gòu)造函數(shù) 只是創(chuàng)建特定類實例(或?qū)ο? 的特殊方法。構(gòu)造函數(shù)方法好比建筑承包人,它利用房子的設(shè)計圖建房子。在 Python 中,構(gòu)造函數(shù)的名稱與其創(chuàng)建的類的名稱相同。類可以有不同的構(gòu)造函數(shù)方法,這些方法是通過類名稱后的圓括號內(nèi)附帶的不同屬性進行區(qū)分。類可以有不同構(gòu)造函數(shù)方法的較好的一個例子就是 int 類, 實際上,您可以用多種方法調(diào)用它,具體采用哪種方法取決于圓括號中放置的參數(shù)(參見清單 2)。
清單 2. Python 解釋器:int 類構(gòu)造函數(shù)
1
2
3
4
5
6
7
8
|
>>> int () 0 >>> int ( 100 ) # Create an integer with the value of 100 >>> int ( "100" , 10 ) # Create an integer with the value of 100 in base 10 100 100 >>> int ( "100" , 8 ) # Create an integer with the value of 100 in base 8 64 |
這四個構(gòu)造函數(shù)調(diào)用創(chuàng)建了四個不同的整數(shù)。第一個構(gòu)造函數(shù)創(chuàng)建了一個整數(shù)對象,其值為 0,在沒有值提供給 int 類構(gòu)造函數(shù)的情況下,該值是所使用的默認值。第二個構(gòu)造函數(shù)根據(jù)規(guī)定創(chuàng)建了一個值為 100 的整數(shù)。第三個構(gòu)造函數(shù)采用了字符串“100”并創(chuàng)建了以 10 為基數(shù)的整數(shù)值(常見的十進制系統(tǒng))。最后一個構(gòu)造函數(shù)也采用了字符串“100”—— 但是它使用基數(shù) 8 來創(chuàng)建整數(shù)值,通常稱為 八進制。不過,該值在輸出時會被轉(zhuǎn)換成十進制數(shù)值,這就是該數(shù)字顯示為 64 的原因。
您可能想知道如果省略了構(gòu)造函數(shù)調(diào)用中的圓括號將會發(fā)生什么。在這種情況下,您可以向該變量分配一個實際的類名稱,有效地為原先的類創(chuàng)建一個別名(參見清單 3)。
清單 3. Python 解釋器:int 類型
1
2
3
4
5
6
7
|
>>> it = int # Create an alias to the integer class >>> it( 100 ) 100 >>> type (it) # We created a new type < type 'type' > >>> type (it( 100 )) # Our new type just makes integers < type 'int' > |
真是太棒了!您立即可以創(chuàng)建一個由內(nèi)置 int 類定義的新數(shù)據(jù)類型。但請注意不好的一面,不要濫用這一新功能。優(yōu)秀的程序員除了使代碼具有良好性能外,還應(yīng)努力使代碼清淅。這類編碼技巧的確有其使用價值,但它們并不常見。
使用 Python 解釋器可以使新的 Python 程序員簡化學(xué)習(xí)過程,少走彎路。如果您想詳細了解 Python 內(nèi)的 help 工具,只需在 Python 解釋器中的命令提示符下鍵入 help() ,就可以訪問交互式的幫助工具(參見清單 4)。
清單 4. Python 解釋器:幫助解釋器
1
2
3
4
5
6
7
8
9
10
11
12
|
>>> help () Welcome to Python 2.4 ! This is the online help utility. If this is your first time using Python, you should definitely check out the tutorial on the Internet at http: / / www.python.org / doc / tut / . Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and return to the interpreter, just type "quit" . To get a list of available modules, keywords, or topics, type "modules" , "keywords" , or "topics" . Each module also comes with a one - line summary of what it does; to list the modules whose summaries contain a given word such as "spam" , type "modules spam" . help > |
您可能已經(jīng)對此有所了解,但在 help> 提示符處輸入 int 可以顯示那些為以前的 int 類顯示的類描述。
容器類型
到目前為止,已經(jīng)談?wù)摿嗽S多 Python 語言中使用的簡單類型。但是多數(shù)程序并不簡單,它們涉及通常由簡單類型組成的復(fù)雜數(shù)據(jù)。因此,現(xiàn)在的問題就成了“如何在 Python 中處理復(fù)雜數(shù)據(jù)?”
如果您熟悉面向?qū)ο蟮恼Z言,如 Java 或 C#,那么您可能認為該問題的答案很簡單:只需創(chuàng)建一個新類來處理復(fù)雜的數(shù)據(jù)即可。該方法也適用于 Python,原因是 Python 支持通過類創(chuàng)建新類型。但是,在多數(shù)情況下,Python 還可以提供更為簡單的方法。當(dāng)您的程序需要一次處理多個對象時,就可以利用 Python 容器類:
tuple
string
unicode
list
set
frozenset
dictionary
這些容器類型提供了兩種功能。前六個類型是有序的,最后一個類型 dictionary 則是一個映射。有序類型與映射類型的區(qū)別較為簡單。有序類型 僅僅是指對象的順序。所有的有序類型(除 set 和 frozenset 類型外)都支持訪問給定順序的對象。相比之下,映射容器 則用于保存那些對順序不是很敏感的對象;通過提供可以找到關(guān)系值的密鑰,就可以從容器中提取值。
容器類型間的另一個不同點來自于它們所持有的數(shù)據(jù)的特性,下面四種容器類型的順序是不可變的:
tuple
string
unicode
frozenset
這意味著在您創(chuàng)建了這些容器類型之一后,所存儲的數(shù)據(jù)就不可更改。如果出于某種原因需要更改數(shù)據(jù),則需要創(chuàng)建一個新容器來保存新的數(shù)據(jù)。
后三種容器類型(list、set 和 dictionary)都是可變?nèi)萜鳎虼耍鼈兛梢愿鶕?jù)需要更改保存的任何數(shù)據(jù)(但在 dictionary 中所使用的密鑰是不可變的,就像您房間的鑰匙)。雖然可變?nèi)萜鞣浅l`活,但它們的動態(tài)特性會對性能造成影響。例如,tuple 類型,盡管它是不可變的,靈活性較差,但在同一環(huán)境中使用時,它們通常比 list 類型快得多。
這些容器類提供了強大的功能,它們通常是多數(shù) Python 程序的核心。本文的其余部分討論了 tuple 類型,它用于引入許多與創(chuàng)建和使用 Python 中的容器類型有關(guān)的基本概念。其余的類型將在以后的文章中討論。
元組
tuple 類型像一個口袋,在出門前可以把所需的任何東西一股腦地放在里面。您可以將鑰匙、駕駛證、便箋簿和鋼筆放在口袋里,您的口袋是存放各種東西的收集箱。Python 的 tuple 類型與口袋類似,它可以存放不同類型的對象。您只需向變量分配一個用逗號分隔的對象序列,就可以創(chuàng)建一個 tuple(參見清單 5)。
清單 5. Python 解釋器:創(chuàng)建一個 tuple
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
>>> t = ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) >>> type (t) < type 'tuple' > >>> t ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) >>> tt = 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 >>> type (tt) < type 'tuple' > >>> tt ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) >>> tc = tuple (( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )) >>> tc ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) >>> et = () # An empty tuple >>> et () >>> st = ( 1 ,) # A single item tuple >>> st ( 1 ,) |
該示例代碼顯示了如何以多種方式創(chuàng)建 tuple。第一種方法是創(chuàng)建一個包含從 0 到 9 整數(shù)序列的 tuple。第二種方法與第一種相同,但這次省去了括號。在創(chuàng)建一個 tuple 時,括號通常是可選的,但有時是必需的,這取決于上下文。結(jié)果,您會習(xí)慣性地使用括號來減少混淆。最后一個 tupletc 使用了一個實際的類構(gòu)造函數(shù)來創(chuàng)建 tuple。這里重要的一點是,構(gòu)造函數(shù)構(gòu)成中僅有一個變量,因此您必須在括號中包括對象序列。最后兩個構(gòu)造函數(shù)調(diào)用演示了如何通過在括號內(nèi)不放任何東西來創(chuàng)建空的 tuple (et),以及如何通過將一個逗號放在序列中僅有的一個項目后面來創(chuàng)建 tuple (st)。
使用口袋裝東西的一個主要原因是為了方便生活。但要求在需要這些東西的時候能夠迅速地從口袋中取出它們。Python 中的多數(shù)容器類型(其中包括 tuple)允許您使用方括號操作符從集合中方便地訪問數(shù)據(jù)項。但 Python 比其他語言更具靈活性:您可以使用通常稱為分段 的方法選擇一個項目或多個有序項目(參見清單 6)。
清單 6. Python 解釋器:從 tuple 訪問項目
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> t = ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) >>> t[ 2 ] 2 >>> type (t[ 2 ]) < type 'int' > >>> t[ 0 ], t[ 1 ], t[ 9 ] ( 0 , 1 , 9 ) >>> t[ 2 : 7 ] # Slice out five elements from the tuple ( 2 , 3 , 4 , 5 , 6 ) >>> type (t[ 2 : 7 ]) < type 'tuple' > >>> t[ 2 : 7 : 2 ] # Slice out three elements from the tuple ( 2 , 4 , 6 ) |
在創(chuàng)建簡單的 tuple 之后,前面的示例顯示如何選擇一個數(shù)據(jù)項 —— 在本示例中是整數(shù) 2。這時,請注意 Python 使用了零排序,其中集合中的項目從零開始編號。如果您熟悉使用 Java 語言、C# 或其他從 C 語言派生的語言進行編程,那么您應(yīng)該非常熟悉此行為。否則,該概念也是非常簡單的。用于訪問數(shù)據(jù)項的索引只聲明集合中越過第一個數(shù)據(jù)項有多遠,或者稱為序列,您需要去獲得所需的內(nèi)容。因此,要獲得第三個數(shù)據(jù)項(在本示例中為整數(shù) 2),您需要從第一個數(shù)據(jù)項起越過兩個數(shù)據(jù)項。在訪問第三個數(shù)據(jù)項時,Python 知道它是一個整數(shù)對象。您還可以方便地從集合中提取多個數(shù)據(jù)項。在本示例中,您創(chuàng)建了一個新的 tuple,其值為從最初的 tuple 開始第一、第二和第十個值。
其余的示例顯示了如何使用 Python 的分段功能從序列中一次選擇多個數(shù)據(jù)項。術(shù)語分段 是指從序列中對數(shù)據(jù)項進行分段的方法。分段的工作方式是聲明開始索引、結(jié)束索引和一個可選的步驟大小,全部都用分號分隔。因此,t[2:7] 將 tuple 中的第三到第七個數(shù)據(jù)項分段,而 t[2:7:2] 則對每兩個數(shù)據(jù)項進行分段,從 tuple 中的第三個數(shù)據(jù)項開始一直到第七個數(shù)據(jù)項。
我目前創(chuàng)建的 tuple 對象是同類的,它們僅包含整數(shù)對象。所幸的是,tuple 要比顯示的示例復(fù)雜得多,因為 tuple 實際上是一個異構(gòu)容器(參見清單 7)。
清單 7. Python 解釋器:異構(gòu)的 tuple
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
>>> t = ( 0 , 1 , "two" , 3.0 , "four" , ( 5 , 6 )) >>> t ( 0 , 1 , 'two' , 3.0 , 'four' , ( 5 , 6 )) >>> t[ 1 : 4 ] ( 1 , 'two' , 3.0 ) >>> type (t[ 2 ]) < type 'str' > >>> type (t[ 3 ]) < type 'float' > >>> type (t[ 5 ]) < type 'tuple' > >>> t[ 5 ] = ( 0 , 1 ) Traceback (most recent call last): File "<stdin>" , line 1 , in ? TypeError: object does not support item assignment |
您會看到,創(chuàng)建可以擁有各種類型數(shù)據(jù)項(其中包括另一 tuple)的 tuple 是多么方便。并且可以使用方括號操作符以相同的方式訪問所有數(shù)據(jù)項,它支持將不同類型的有序數(shù)據(jù)項分段。然而,tuple 是不可變的。因此,當(dāng)我嘗試更改第五個元素時,發(fā)現(xiàn)不允許對數(shù)據(jù)項分配。打一個簡單的比方,在您將某些東西放入口袋后,改變所取東西的惟一方式是取一個新口袋,并將所有數(shù)據(jù)項放進去。
如果需要在現(xiàn)有 tuple 中創(chuàng)建一個包含數(shù)據(jù)項子集的新 tuple,最簡單的方法是使用相關(guān)的片段,并根據(jù)需要同時添加子集(參見清單 8)。
清單 8. Python 解釋器:使用 tuple
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> tn = t[ 1 : 3 ] + t[ 3 : 6 ] # Add two tuples >>> tn ( 1 , 'two' , 3.0 , 'four' , ( 5 , 6 )) >>> tn = t[ 1 : 3 ] + t[ 3 : 6 ] + ( 7 , 8 , 9 , "ten" ) >>> tn ( 1 , 'two' , 3.0 , 'four' , ( 5 , 6 ), 7 , 8 , 9 , 'ten' ) >>> t2 = tn[:] # Duplicate an entire tuple, a full slice >>> t2 ( 1 , 'two' , 3.0 , 'four' , ( 5 , 6 ), 7 , 8 , 9 , 'ten' ) >>> len (tn) # Find out how many items are in the tuple 9 >>> tn[ 4 ][ 0 ] # Access a nested tuple 5 |
您還可以將現(xiàn)有 tuple 的片段與新 tuple 的片段合并在一起。使用片段語法,無需指定開始或結(jié)束索引,就可以制作現(xiàn)有 tuple 的副本。最后兩個示例也非常有趣。內(nèi)置的 len 方法告訴您 tuple 中數(shù)據(jù)項的數(shù)量。從嵌套的 tuple 訪問數(shù)據(jù)項也非常簡單:選擇嵌套的 tuple,然后從中訪問有趣的數(shù)據(jù)項。
您還可以從稱為打包 的過程的一組現(xiàn)有變量中創(chuàng)建一個tuple。反之亦然,其中,tuple 中的值被指派給變量。這之后的過程稱為解包,它是用于許多情形的功能十分強大的技術(shù),其中包括希望從一個函數(shù)中返回多個值。在解包 tuple 時,僅有的問題是必須為 tuple 中的每個數(shù)據(jù)項提供一個變量(參見清單 9)。
清單 9. Python 解釋器:打包和解包 tuple
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> i = 1 >>> s = "two" >>> f = 3.0 >>> t = (i, s, f) # Pack the variables into a tuple >>> t ( 1 , 'two' , 3.0 ) >>> ii, ss, ff = t # Unpack the tuple into the named variables >>> ii 1 >>> ii, ff = t # Not enough variables to unpack three element tuple Traceback (most recent call last): File "<stdin>" , line 1 , in ? ValueError: too many values to unpack |
簡化概念
盡管看上去十分復(fù)雜,但 Python 的對象屬性實際上簡化了 Python 語言新手常常面臨的一些更為復(fù)雜的概念。在了解如何使用對象之后,所有東西都是對象這一概念意味著您已經(jīng)進一步理解了一些新概念。如 Python 的容器類型。使困難的任務(wù)變得簡單化是使用 Python 得到的常見好處之一;另一個例子是內(nèi)置的幫助工具,只需在 Python 提示符處輸入 help(),就可以在 Python 解釋器中看到該工具。由于生活不是用一些簡單的概念描述的,所以 Python 提供了一組豐富的容器(即集合)對象。在本文中,我介紹了其中的最簡單的對象 —— tuple。要正確使用 tuple,就需要熟悉它的工作方式。但是,由于許多其他容器類型具有類似的功能,其中包括分段以及打包或解包,了解 tuple 的工作原理意味著您已經(jīng)開始完全理解 Python 中的其他容器類型。