在底下的例子裡,你可以很容易區別凡是需要輸入的地方都會出現prompts (">>
> " 或 "... "),凡是輸出的結果則沒有。如果你想要跟著這個教學文件一起做的話,你就得打入所有在prompts之後的指令,凡是沒有prompts出現的行就是直譯器輸出的結果。值得注意的是,secondary
promt 之後如果什麼東西都沒有,表示這是一個空行(直接按ENTER的結果),也表示這是一個多行指令的結束。
在本文件中的大部分例子,都有加上注釋,甚至是那些互動模式下的例子。注釋(comment)在Python中是以 " #" 之後的東西都是注釋(譯:跟Perl一樣)。注釋可以自成一行,也可以跟在空白字元或是程式碼的後面。但是,如果 " #" 是在字串常數(string literal)之中的話,就不代表注釋的意義,而只是一個普通字元罷了。
底下是一些例子:
# this is the first comment
SPAM = 1 # and this is the second comment
# ... and now a third!
STRING = "# This is not a comment."
現在我們來試一試一些簡單的Python指令吧。請先啟動Python的直譯器並且等待primary prompt( "
>>
> " )的出現。(應該不會很久的)
直譯器就好像一個計算機一樣:你可以打入一個表示式(expression),然後直譯器會把這個expression的執行結果秀出來。Expression的語法都很簡單直接,一般的運算符號
+
, -
, *
以及 /
的用法就跟其他的程式語言(像是Pascal或C)一樣。你也可以用括號
"( )" 來表示運算執行的先後次序。例子如下:
>>> 2+2
4
>>> # This is a comment
... 2+2
4
>>> 2+2 # and a comment on the same line as code
4
>>> (50-5*6)/4
5
>>> # Integer division returns the floor:
... 7/3
2
>>> 7/-3
-3
跟C語言一樣,等於符號 ("=") 其實是表示設定某個值給一個變數的意思。雖然設定 ("=") 運算本身是有結果值的,但是直譯器並不會輸出其結果來。
>>> width = 20
>>> height = 5*9
>>> width * height
900
一個值是可以同時設給許多變數的:
>>> x = y = z = 0 # Zero x, y and z
>>> x
0
>>> y
0
>>> z
0
浮點數的運算在Python裡面也是支援的,如果整數與浮點數(帶小數點或e的數)進行運算的話,整數部分會先轉換(convert)成浮點數再進行運算。
>>> 4 * 2.5 / 3.3
3.0303030303
>>> 7.0 / 2
3.5
甚至連複數的運算也支援喔,只需要把虛數部分加上 "j" 或是 " J"在其後就可以了。如果實部不為零的話,複數的寫法就寫成 "(real+ imagj)" 。或者,我們也可以用函數的方式來表示複數為 "complex(real , imag)" 的形式。
>>> 1j * 1J
(-1+0j)
>>> 1j * complex(0,1)
(-1+0j)
>>> 3+1j*3
(3+3j)
>>> (3+1j)*3
(9+3j)
>>> (1+2j)/(1+1j)
(1.5+0.5j)
複數的虛數部分及實數部分的值都是以浮點數(float point numbers)來表示的,如果 z
代表一個複數的話,你可以很輕易的用 z.real
以及 z.imag
得到一個複數的實數部分及虛數部分。
>>> a=1.5+0.5j
>>> a.real
1.5
>>> a.imag
0.5
複數沒有辦法直接用 (float(),
int() 或是 long()) 轉換成浮點數或是整數。事實上,複數沒有直接對應的實數,你必須用
abs(z)
來得到 z
的magnitude(以浮點數表示),或是如上所述
用z.real
直接得到其實數部分。
>>> a=1.5+0.5j
>>> float(a)
Traceback (innermost last):
File "<stdin>", line 1, in ?
TypeError: can't convert complex to float; use e.g. abs(z)
>>> a.real
1.5
>>> abs(a)
1.58113883008
在互動模式之下,最後一個印出來的expression的值會儲存在一個特殊變數 "_
" 之中。這表示,當你用Python的直譯器來當作計算機用的時候,想要連續做運算其實是方便許多的。如下例:
>>> tax = 17.5 / 100
>>> price = 3.50
>>> price * tax
0.61249999999999993
>>> price + _
4.1124999999999998
>>> round(_, 2)
4.1100000000000003
對於使用者來說, "_
" 這個變數是一個唯讀的變數。你沒有辦法設定一個值給它,當你這樣做的時候,事實上你是重新創造一個同名的變數,但是跟之前系統內建的
"_
" 這個變數是一點關係也沒有的了。
除了數字之外, Python也有能力處理字串(string)。字串在Python中有很多種表達方式,它可以放在雙括號””之中,也可以放在單括號’’裡面:
>>> 'spam eggs'
'spam eggs'
>>> 'doesn\'t'
"doesn't"
>>> "doesn't"
"doesn't"
>>> '"Yes," he said.'
'"Yes," he said.'
>>> "\"Yes,\" he said."
'"Yes," he said.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
字串常數(string literals)是可以跨越多行的,其表示方法有很多。如果要換行的話可以用”\”符號來表示之。如下例:
hello = "This is a rather long string containing\n\
several lines of text just as you would do in C.\n\
Note that whitespace at the beginning of the line is\
significant.\n"
print hello
這個例子會印出以下的結果:
This is a rather long string containing
several lines of text just as you would do in C.
Note that whitespace at the beginning of the line is significant.
你也可以用成對的三個單引號( """
) 或雙引號 (
'''
) 來表示字串。在此情況下你所打入的ENTER就會直接被解讀為換行符號而不需要再用\n了。
print """
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
"""
這個例子會印出以下的結果:
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
如果你打入的expression是字串的運算,運算的結果的同樣的會由直譯器顯示出來,而且顯示的方式跟你直接打入字串常數(string literals)是一樣的:會在引號之中,所有有escape character “\”表示的字元都會依樣的顯示出來。如果字串本身包含有單引號,整個字串就會用雙引號括起來,要不然就會只用單引號來把整個字串括起來。(如果你使用 print 這個敘述(statement)來印出字串的話,螢幕的輸出就不會有引號出現,而且字串中的escape character (\”表示的特殊字元) 都會顯示出其所代表的意義來。)
字串可以用 +
這個運算元來相加 (連接起來),或是用
*
這個運算元來重複之。請看例子:
>>> word = 'Help' + 'A'
>>> word
'HelpA'
>>> '<' + word*5 + '>'
'<HelpAHelpAHelpAHelpAHelpA>'
如果你把兩個字串常數放在一起,它們自動就會相加起來。所以,上面的例子的第一行也可以寫作 "word = 'Help' 'A'" 。不過這個方法只適用於兩個字串常數的相加,其他情況就不適合了。請看例子:
>>> import string
>>> 'str' 'ing' # <- This is ok
'string'
>>> string.strip('str') + 'ing' # <- This is ok
'string'
>>> string.strip('str') 'ing' # <- This is invalid
File "<stdin>", line 1
string.strip('str') 'ing'
^
SyntaxError: invalid syntax
如同在C語言一樣,字串是有標記(subscript(index))的,第一個字元的標記(subscript(index))就是0。在Python中沒有另外一個字元character資料型態,一個字元就是一個長度為 1的字串。就像是在Icon語言一樣,字串是可以用其subscript(index)來切出( slice notation )其中的一部份的,其語法為 ""。
>>> word[4]
'A'
>>> word[0:2]
'He'
>>> word[2:4]
'lp'
與C不同的是,Python的字串是不可改變的(immutable),如果你想要改變其中的一個字元或是一個部份(slice),你會得到一個錯誤的信息:
>>> word[0] = 'x'
Traceback (innermost last):
File "<stdin>", line 1, in ?
TypeError: object doesn't support item assignment
>>> word[:-1] = 'Splat'
Traceback (innermost last):
File "<stdin>", line 1, in ?
TypeError: object doesn't support slice assignment
但是你可以任意使用一個字串的一個字元或是一個部份(slice)來創造出另一個字串,這是完全可行的:
>>> 'x' + word[1:]
'xelpA'
>>> 'Splat' + word[-1:]
'SplatA'
當你用字串切片(string slice)的語法時,可以使用其預定(default)的subscript(index)值,這是很方便的。第一個subscript(index)的預設值是0,第二個subscript(index)的預設值則是這個字串的整體長度。
>>> word[:2] # The first two characters
'He'
>>> word[2:] # All but the first two characters
'lpA'
所以, s[:i] + s[i:]
會恰好等於 s
。你可以想一想為什麼:
>>> word[:2] + word[2:]
'HelpA'
>>> word[:3] + word[3:]
'HelpA'
如果你用一些奇怪的index來切割字串,Python直譯器也都處理的很好:如果第二個index太大的話就自動代換為字串的長度,如果第二個index比第一個index還要小的話就自動傳回 一個空字串。
>>> word[1:100]
'elpA'
>>> word[10:]
''
>>> word[2:1]
''
字串的index甚至可以是負數,若是負數的話,就必須從字串的尾巴開始算起。如下例:
>>> word[-1] # The last character
'A'
>>> word[-2] # The last-but-one character
'p'
>>> word[-2:] # The last two characters
'pA'
>>> word[:-2] # All but the last two characters
'Hel'
但是 -0 事實上是等於 0 ,所以不會從尾巴開始算起。
>>> word[-0] # (since -0 equals 0)
'H'
如果負數index超過字串的範圍的話,就自動只會到最大可能的範圍,但是如果不是切割一部份的話就會造成錯誤的情形:
>>> word[-100:]
'HelpA'
>>> word[-10] # error
Traceback (innermost last):
File "<stdin>", line 1
IndexError: string index out of range
最好避免錯誤的方法是把index看成是指向字元及字元間位置的指標,字串的最開頭是0,字串的結尾處就是字串的長度。如下圖所示:
+---+---+---+---+---+
| H | e | l | p | A |
+---+---+---+---+---+
0 1 2 3 4 5
-5 -4 -3 -2 -1
上圖的數字部分第一行代表的是正數的index,由0到字串的長度,第二行代表的是負數的index。字串的切片(slice)很容易就可以看出來,就是兩個index之間的所有字元組合成的字串囉。
對於正數的index來說,如果兩個index都在範圍之內,字串的切片(slice)的長度就正好是其兩個index相減的結果。舉例來說
word[1:3]
的長度就正好是 2。
Python內建的 len() 函式可以幫助我們得到字串的長度值。
>>> s = 'supercalifragilisticexpialidocious'
>>> len(s)
34
從Python 2.0 開始Python支援一種新的儲存文字資料的資料型態:Unicode物件(object)。使用這個物件你可以儲存並控制Unicode的資料(詳見 http://www.unicode.org ) ,並且這個物件跟已經存在的字串(string)物件是完全可以互相整合,並且在需要時可以互相轉換的。
使用Unicode的好處是可以處理各種不同國家語言的字元。在Unicode之前,在一個code page裡只有256個字元可以使用在script中。這個限制的結果常常造成軟體國際化(internationalizetion,通常寫作 "i18n" -- "i" + 18個字元 + "n")時候的困擾。Unicode的出現定義一個所有script都可以用的code page,如此就解決了這個問題。
在Python中要創造一個Unicode字串就跟創造一個普通字串一樣容易:
>>> u'Hello World !'
u'Hello World !'
在引號之前小寫的 "u" 代表這個字串是一個Unicode字串。如果你要用到特殊字元,你可能要使用Python的Unicode特殊字元編碼( Unicode-Escape encoding)。底下的範例示範如何使用之:
>>> u'Hello\\u0020World !'
u'Hello World !'
上面的
表示在這個位置要插入一個由十六位元0x0020所代表的Unicode字元 (就是空白字元啦)。
u0020
其他的字元也是一樣的會被解讀為其對應的Unicode字元。由於Unicode對應中的前256 個Unicode字元正好就是大部分歐美國家使用的Latin-1 編碼字元,所以其轉換是更加的容易。
對於專家們來說,有一個字串的原始模式(raw mode)可以使用。你必須再加上一個小寫 'r' 來使Python 使用這一個原始的Unicode特殊字元編碼(
Raw-Unicode-Escape
encoding)。只有當
之中的小寫 'r' 有奇數的'\'時才會用到這一個編碼的。
uXXXX
>>> ur'Hello\u0020World !'
u'Hello World !'
>>> ur'Hello\\u0020World !'
u'Hello\\\\u0020World !'
這個原始模式(raw mode)通常用在當你的字串裡面有一大堆的反斜線 '\' 時 ,例如regular expressions(正規表示)時就常用到。
除了這些標準的編碼之外, Python還提供了一整套的方法讓你可以從以知的編碼中創造出Unicode字串來。
Python內建的 unicode() p() 函式可以讓你使用所有的已註冊的Unicode解碼/編碼系統(codecs (COders and DECoders))。 這個 codes 可以與大部分的系統互相轉換,包括 Latin-1, ASCII , UTF-8 以及 UTF-16 等等。上面所提到的最後兩種系統是可變長度的編碼系統,可以來儲存8位元及16位元的Unicode字元。Python預設使用UTF-8為預設編碼系統。當你印出Unicode或是將Unicode寫入檔案時都會使用到。
>>> u"äöü"
u'\344\366\374'
>>> str(u"äöü")
'\303\244\303\266\303\274'
如果你要使用一個特別的編碼系統,但是要印出對應的Unicode碼時,你可以使用 unicode() 函式,加上這個編碼系統的名稱當作第二個參數。
>>> unicode('\303\244\303\266\303\274','UTF-8')
u'\344\366\374'
如果要把Unicode字串轉換為一般的字串編碼時,可以使用Unicode物件的 encode() 方法(method)。
>>> u"äöü".encode('UTF-8')
'\303\244\303\266\303\274'
(譯:硬要翻譯list實在太不方便,我直接用原文囉)
Python能夠了解一些較為 複雜 的資料型態,這些資料型態大多是用來處理一群的其他資料值。最方便使用的要算是 list 了,一個list可以寫成一串由逗號分開的值(東西),然後用角括號括起來便成。放在list裡的東西不需要是同一個資料型態
>>> a = ['spam', 'eggs', 100, 1234]
>>> a
['spam', 'eggs', 100, 1234]
跟字串的index用法相同,list的index也由0開始,同樣你可以用index來切割lists、組合兩個list等等:
>>> a[0]
'spam'
>>> a[3]
1234
>>> a[-2]
100
>>> a[1:-1]
['eggs', 100]
>>> a[:2] + ['bacon', 2*2]
['spam', 'eggs', 'bacon', 4]
>>> 3*a[:3] + ['Boe!']
['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boe!']
與字串不相同的是,字串的個別字元是不可變動的( immutable ),但是list的個別成員是可以自由改變的。
>>> a
['spam', 'eggs', 100, 1234]
>>> a[2] = a[2] + 23
>>> a
['spam', 'eggs', 123, 1234]
你也可以設定一個值或是一個list給一個list的切割部分(slice),但是這樣的結果會改變整個list的長度:
>>> # Replace some items:
... a[0:2] = [1, 12]
>>> a
[1, 12, 123, 1234]
>>> # Remove some:
... a[0:2] = []
>>> a
[123, 1234]
>>> # Insert some:
... a[1:1] = ['bletch', 'xyzzy']
>>> a
[123, 'bletch', 'xyzzy', 1234]
>>> a[:0] = a # Insert (a copy of) itself at the beginning
>>> a
[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234]
內建的 len() 函式仍然可用在list上面:
>>> len(a)
8
一個list也可以是另一個list的成員(這叫作巢狀list, nested list),參考下例:
>>> q = [2, 3]
>>> p = [1, q, 4]
>>> len(p)
3
>>> p[1]
[2, 3]
>>> p[1][0]
2
>>> p[1].append('xtra') # See section 5.1
>>> p
[1, [2, 3, 'xtra'], 4]
>>> q
[2, 3, 'xtra']
注意前一個例子, p[1]
以及 q
事實上指得是同一個物件。我們在之後還會再討論物件的語法( object semantics
)。
當然Python能做比二加二更有用更複雜的事,例如說,我們可以寫一個程式來印出費氏數列( the Fibonacci series )來:
>>> # Fibonacci series:
... # the sum of two elements defines the next
... a, b = 0, 1
>>> while b < 10:
... print b
... a, b = b, a+b
...
1
1
2
3
5
8
這個範例告訴了我們很多新的事情:
a
以及
b
同時都設定了新的值0 與 1。 程式的最後一行再次使用這個技巧,這次在設定符號(等號)的右邊我們使用了expression,所有在右邊的expression會先求得其值(evaluate)然後才進行設定(assign)的動作。對於在右邊的expression來說,其evaluate的次序則是由左至右的。
b < 10
), 這個while 迴圈就會一直執行。與C相同的是,對Python而言只要是非零的整數都代表在決定true/false的情況下都代表true,0則代表false。我們也可以在迴圈的條件的地方放入字串或是一個list,只要這個字串或list的長度不是零就代表true,若是空字串或空的list就代表false。在這個例子裡,我們比較兩個值的大小。比較的運算元與C是完全相同的:
<
(小於), >
(大於), ==
(等於),
<=
(小於或等於), >=
(大於或等於) 以及 !=
(不等於)。
>>> i = 256*256
>>> print 'The value of i is', i
The value of i is 65536
如果不想每次的輸出都換行的話可以在 print 敘述之後加上逗號,如下所示:
>>> a, b = 0, 1
>>> while b < 1000:
... print b,
... a, b = b, a+b
...
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
值得注意的是如果最後一行還沒有完成的話,直譯器會在印出prompt之前印出新的一行。