第二堂上課囉!在知道怎麼撰寫、執行第一個 Python 程式之後,接下來就要瞭解一下 Python 這個程式語言,只不過我們只剩五個小時,因而採取的方式是,在這一個小時很快地瀏覽過 Python 語言的重要基本元素,之後四個小時再從更多實際的範例中瞭解 Python 語言。 那麼,哪些東西才是語言中重要而基本的元素呢?Pascal 之父 Niklaus E. Writh 曾說過:
Algorithms + Data Structures = Programs
演算法與資料結構就等於程式,而一門語言提供的資料型態(Data type)、運算子(Operator)、程式碼封裝方式等,會影響演算法與資料結構的實作方式,因此這一堂對於 Python 語言講解的重點將選定在:- 內建型態(Built-in type)、變數(Variable)與運算子(Operator)
- 函式(Function)、類別(Class)、模組(Module)與套件(Package)
內建型態
在 Python 中,萬物皆物件!不過,物件導向並非 Python 的主要典範(Paradigm),Python 之父 Guido van Rossum 曾言,自己並非物件導向之信徒,在《Masterminds of Programming》書中,Guido van Rossum 說到:Python 支援程序式的(Procedural)程式設計以及(某些程度)物件導向。這兩者沒太大不同,然而 Python 的程序式風格仍強烈受到物件影響(因為基礎的資料型態都是物件)。Python 支援小部份函數式(Functional)程式設計 -- 不過它不像任何真正的函數式語言。
無論如何,接下來要認識的內建型態都是物件,像是:- 數值型態(Numeric type) -
int, long, float, bool, complex
- 字串型態(String type)
- 容器型態(Container type) -
list, set, dict, tuple
數值型態
我們直接進入 Python 互動環境來瞭解這些型態吧!可以使用type
函式來得知值的型態。首先是數值型態:
~$ python
Python 2.7.3 (default, Aug 1 2012, 05:16:07)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> type(1) # 1 是什麼型態?
<type 'int'>
>>> type(1L) # 加上 L 呢?
<type 'long'>
>>> type(111111111111111111111111111111111) # 太長的整數會自動使用 long 型態
<type 'long'>
>>> type(3.14) # 浮點數是 float 型態
<type 'float'>
>>> type(True) # 布林值是 bool 型態
<type 'bool'>
>>> type(3 + 4j) # 支援複數的 complex 型態
<type 'complex'>
>>> 2 ** 100 # 2 的 100 次方
1267650600228229401496703205376L
>>>
上面的範例中使用了
**
運算子進行次方運算,Python 中當然有加(+
)、減(-
)、乘(*
)等運算子,至於除法則有 /
除法(division)運算子與 //
浮點除法(floor division)兩個,在 Python 2.7 中,整數與整數進行 /
或 //
運算會產生整數;然而整數與浮點數進行 /
會保留小數部份,若進行 //
則會截去小數部份:
>>> 10 / 3
3
>>> 10 // 3
3
>>> 10 / 3.0
3.3333333333333335
>>> 10 // 3.0
3.0
>>>
然而
/
//
/
卻是會產生浮點數,原因可看看 Python Taiwan 社團的討論:
>>> 10 / 3
3.3333333333333335
>>> 10 // 3
3
>>> 10 / 3.0
3.3333333333333335
>>> 10 // 3.0
3.0
>>>
在浮點數精確度的表現上,也有必須注意的地方。例如:
>>> 1.0 - 0.8
0.19999999999999996
>>> print (1.0 - 0.8)
0.2
>>>
多數 CPU 與浮點運算器多採用 IEEE754 浮點數運算(IEEE 754 floating-point arithmetic),某些浮點數本身就有誤差,這是每個程式人都應該知道的事。Python 互動環境在顯示值時,採用制式的(Offical)字串表示,而
print
語句則採用了非正式的(Informal)字串表示;技術上來說,Python 互動環境會利用物件的 __repr__
方法傳回的字串來顯示,print
語句會利用物件的 __str__
方法傳回的字串來顯示:
>>> repr(1.0 - 0.8)
'0.19999999999999996'
>>> str(1.0 - 0.8)
'0.2'
>>>
雖然你也可以用
(1.0 - 0.8).__repr__()
、(1.0 - 0.8).__str__()
來取得字串,不過在 Python 中,底線開頭暗示著你不要直接呼叫或使用,因此上面的示範中,使用 repr
及 str
函式來取得字串。日後你繼續學習 Python 語言的過程中,你會知道,__repr__
及 __str__
是可以自行定義的。 簡單來說,用
__repr__
來傳回沒有岐義的(Unambiguous)字串表示,用 __str__
來傳回具可讀性的(Readable)字串表示。 想要精確地表示浮點數,語言都會提供程式庫,Python 中使用 decimal
模組中的 Decimal
類別來進行處理。例如:
>>> import decimal
>>> a = decimal.Decimal('1.0')
>>> b = decimal.Decimal('0.8')
>>> a - b
Decimal('0.2')
>>> print (a - b)
0.2
>>>
字串型態
如果要在 Python 中表示字串,可以使用''
或 ""
包括文字,兩者在 Python 中具相同作用,都可產生 str
實例,可視情況互換。例如:
>>> "Just'in"
"Just'in"
>>> 'Just"in'
'Just"in'
>>> 'c:\workspace'
'c:\\workspace'
>>> "c:\workspace"
'c:\\workspace'
>>>
可以看到,在某些情況下,你不用特別略過(Escape)
\
字元,然而在底下這種情況下就需要了:
>>> 'c:\todo'
'c:\todo'
>>> print 'c:\todo'
c: odo
>>> print 'c:\\todo'
c:\todo
>>>
可以在字串前加上
r
,表示接下來後面是原始字串(Raw string)表示,這樣 Python 就會忠實表示後續的字串,技術上來說,會自動為你處理需要略過的字元。例如:
>>> r'c:\todo'
'c:\\todo'
>>> print r'c:\todo'
c:\todo
>>>
Python 中的字串不可變(Immutable),你無法改變已建立的字串內容;想得知字串實際的位元組序列長度(不一定是字元長度),可以使用
len
函式;可以使用 for
來迭代字串;可以使用 in
來測試字串是否包括某子字串;可以使用 +
來串接字串;可以使用 *
來複製字串。例如:
>>> name = 'Justin'
>>> len(name)
6
>>> for ch in name:
... print ch
...
J
u
s
t
i
n
>>> 'Just' in name
True
>>> name + name
'JustinJustin'
>>> name * 3
'JustinJustinJustin'
>>>
可以使用
[]
指定索引來取得字串中的某個字元,索引從 0
開始,可以是正數或負數,負數表示從尾端開始計數,例如 -1
就是最後一個字元, -2
就是倒數第二個字元,依此類推。例如:
>>> lang = 'Python'
>>> lang[0]
'P'
>>> lang[-1]
'n'
>>>
[]
也可以用來切割字串,例如:
>>> lang[1:5] # 取得索引 1 至 5(包括 1 但不包括 5)的子字串
'ytho'
>>> lang[0:] # 省略結尾索引,表示取至尾端
'Python'
>>> lang[:6] # 省略起始索引,表示從 0 開始
'Python'
>>>
[]
還可以指定間距(Gap),例如取索引 0 至 6,每 2 個間距的方式取子字串:
>>> lang[0:6:2]
'Pto'
>>>
'Python'
的 'P'
至 'y'
算一個間距,'y'
與 't'
之間也是一個間距,依此類推 'Python'[0:6:2]
取得的就是 'Pto'
,將以上對 []
的運算方式組合在一起,可以得到一個有趣的反轉字串方式 [::-1]
:
>>> lang[::-1]
'nohtyP'
>>>
如果要進行字串格式化,以下是舊式寫法:
>>> '%d %.2f %s' % (1, 99.3, 'Justin')
'1 99.30 Justin'
>>> '%(real)s is %(nick)s' % {'real' : 'Justin', 'nick' : 'caterpillar'}
'Justin is caterpillar'
>>>
技術上來說,字串物件將
%
定義為格式化操作,可以接受 tuple
與 dict
型態,不過這種寫法可讀性不好,從 Python 2.6 之後,建議使用字串的 format
方法來取代 %
操作:
>>> '{0} is {1}'.format('Justin', 'caterpillar')
'Justin is caterpillar'
>>> '{real} is {nick}'.format(real = 'Justin', nick = 'caterpillar')
'Justin is caterpillar'
>>> '{0} is {nick}'.format('Justin', nick = 'caterpillar')
'Justin is caterpillar'
>>> import sys
>>> 'My platform is {pc.platform}'.format(pc = sys)
'My platform is linux2'
>>>
容器型態及
if
、for
、while
等流程語法,會在下篇文章中說明,建議你也趁這個機會,在 Python 互動環境中,進行上面看到的範例練習。