- 論壇徽章:
- 1
|
Python 指南
3. Python的非正式介紹
在后面的例子中,區(qū)分輸入和輸出的方法是看是否有提示符(“>;>;>; ”和“.. ”):想要重復這些例子的話,你就要在提示符顯示后輸入所有的一切;沒有以提示符開始的行,是解釋器輸出的信息。需要注意的是示例中的從屬提示符用于多行命令的結束,它表示你需要輸入一個空行。
本手冊中的很多示例都包括注釋,甚至有一些在交互提示符中折行。Python中的注釋以符號“#”起始,一直到當前行的結尾。注釋可能出現(xiàn)在一行的開始,也可能跟在空格或程序代碼之后,但不會出現(xiàn)在字符串中,字符串中的#號只代表#號。
示例:
# this is the first comment
SPAM = 1 # and this is the second comment
# ... and now a third!
STRING = "# This is not a comment."
3.1 初步認識Python
讓我們試驗一些簡單的Python命令。啟動解釋器然后等待主提示符“>;>;>; ”出現(xiàn)(這用不了太久)。
3.1.1 數(shù)值
解釋器的行為就像是一個計算器。你可以向它輸入一個表達式,它會返回結果。表達式的語法簡明易懂:+,-,*,/和大多數(shù)語言中的用法一樣(比如C或Pascal),括號用于分組。例如:
>;>;>; 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完全支持浮點數(shù),不同類型的操作數(shù)混在一起時,操作符會把整型轉化為浮點數(shù)。
>;>;>; 3 * 3.75 / 1.5
7.5
>;>;>; 7.0 / 2
3.5
復數(shù)也同樣得到了支持,虛部由一個后綴“j”或者“J”來表示。帶有非零實部的復數(shù)記為“(real+imagj)”,或者也可以通過“complex(real, imag)”函數(shù)創(chuàng)建。
>;>;>; 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)
復數(shù)總是由實部和虛部兩部分浮點數(shù)來表示?赡軓 z.real 和 z.imag 得到復數(shù)z的實部和虛部。
>;>;>; a=1.5+0.5j
>;>;>; a.real
1.5
>;>;>; a.imag
0.5
用于向浮點數(shù)和整型轉化的函數(shù)(float(), int() 和 long())不能對復數(shù)起作用--沒有什么方法可以將復數(shù)轉化為實數(shù)?梢允褂胊bs(z)取得它的模,也可以通過z.real得到它的實部。
>;>;>; a=3.0+4.0j
>;>;>; float(a)
Traceback (most recent call last):
File "<stdin>;", line 1, in ?
TypeError: can't convert complex to float; use e.g. abs(z)
>;>;>; a.real
3.0
>;>;>; a.imag
4.0
>;>;>; abs(a) # sqrt(a.real**2 + a.imag**2)
5.0
>;>;>;
交互模式下,最近一次表達式輸出保存在_變量中。這意味著把Python當做桌面計算器使用時,它可以更容易的進行連續(xù)計算,例如:
>;>;>; tax = 12.5 / 100
>;>;>; price = 100.50
>;>;>; price * tax
12.5625
>;>;>; price + _
113.0625
>;>;>; round(_, 2)
113.06
>;>;>;
這個變量對于用戶來說是只讀的。不要試圖去給它賦值--由于Python的語法效果,你只會創(chuàng)建一個同名的局部變量覆蓋它。
3.1.2 字符串
除了數(shù)值,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.'
字符串可以通過幾種方式分行?梢栽谛屑臃葱备茏鰹槔^續(xù)符,這表示下一行是當前行的邏輯沿續(xù)。
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."
print hello
注意換行用 \n 來表示;反斜杠后面的新行標識(newline,縮寫“n”)會轉換為換行符,示例會按如下格式打。
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.
然而,如果我們創(chuàng)建一個“raw”行,\n序列就不會轉為換行,示例源碼最后的反斜杠和換行符n都會做為字符串中的數(shù)據(jù)處理。如下所示:
hello = r"This is a rather long string containing\n\
several lines of text much as you would do in C."
print hello
會打印為:
This is a rather long string containing\n\
several lines of text much as you would do in C.
或者,字符串可以用一對三重引號”””或'''來標識。三重引號中的字符串在行尾不需要換行標記,所有的格式都會包括在字符串中。
print """
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
"""
produces the following output:
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
解釋器打印出來的字符串與它們輸入的形式完全相同:內部的引號,用反斜杠標識的引號和各種怪字符,都精確的顯示出來。如果字符串中包含單引號,不包含雙引號,可以用雙引號引用它,反之可以用單引號。(后面介紹的print語句,可以可以用來寫沒有引號和反斜杠的字符串)。
字符串可以用+號聯(lián)接(或者說粘合),也可以用*號循環(huán)。
>;>;>; word = 'Help' + 'A'
>;>;>; word
'HelpA'
>;>;>; '<' + word*5 + '>;'
'<HelpAHelpAHelpAHelpAHelpA>;'
兩個字符串值之間的聯(lián)接是自動的,上例第一行可以寫成“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, in ?
string.strip('str') 'ing'
^
SyntaxError: invalid syntax
字符串可以用下標(索引)查詢;就像C一樣,字符串的第一個字符下標是0。這里沒有獨立的字符類型,字符僅僅是大小為一的字符串。就像在Icon中那樣,字符串的子串可以通過切片標志來表示:兩個由冒號隔開的索引。
>;>;>; word[4]
'A'
>;>;>; word[0]
'He'
>;>;>; word[2]
'lp'
切片索引可以使用默認值;省略前一個索引表示0,省略后一個索引表示被切片的字符串的長度。
>;>;>; word[] # The first two characters
'He'
>;>;>; word[2:] # All but the first two characters
'lpA'
和C字符串不同,Python字符串不能改寫。按字符串索引賦值會產生錯誤。
>;>;>; word[0] = 'x'
Traceback (most recent call last):
File "<stdin>;", line 1, in ?
TypeError: object doesn't support item assignment
>;>;>; word[] = 'Splat'
Traceback (most recent call last):
File "<stdin>;", line 1, in ?
TypeError: object doesn't support slice assignment
然而,可以通過簡單有效的組合方式生成新的字符串:
>;>;>; 'x' + word[1:]
'xelpA'
>;>;>; 'Splat' + word[4]
'SplatA'
切片操作有一個很有用的不變性: s[] + s[i:] 等于s。
>;>;>; word[] + word[2:]
'HelpA'
>;>;>; word[] + word[3:]
'HelpA'
退化的切片索引被處理的很優(yōu)美:過大的索引代替為字符串大小,下界比上界大的返回空字符串。
>;>;>; word[1]
'elpA'
>;>;>; word[10:]
''
>;>;>; word[2]
''
索引可以是負數(shù),計數(shù)從右邊開始,例如:
>;>;>; 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,所以它不是從右邊計數(shù)的!
>;>;>; word[-0] # (since -0 equals 0)
'H'
越界的負切片索引會被截斷,不過不要嘗試在前元素索引(非切片的)中這樣做:
>;>;>; word[-100:]
'HelpA'
>;>;>; word[-10] # error
Traceback (most recent call last):
File "<stdin>;", line 1, in ?
IndexError: string index out of range
理解切片的最好方式是把索引視為兩個字符之間的點,第一個字符的左邊是0,字符串中第n個字符的右邊是索引n,例如:
+---+---+---+---+---+
| H | e | l | p | A |
+---+---+---+---+---+
0 1 2 3 4 5
-5 -4 -3 -2 -1
第一行是字符串中給定的0到5各個索引的位置,第二行是對應的負索引。從i到j的切片由這兩個標志之間的字符組成。
對于非負索引,切片長度就是兩索引的差。例如,word[1]的長度是2。
內置函數(shù) len() 返回字符串長度:
>;>;>; s = 'supercalifragilisticexpialidocious'
>;>;>; len(s)
34
3.1.3 Unicode 字符串
從Python2.0開始,程序員們可以使用一種新的數(shù)據(jù)類型來存儲文本數(shù)據(jù):Unicode 對象。它可以用于存儲多種Unicode數(shù)據(jù)(請參閱 http://www.unicode.org/ ),并且,通過必要時的自動轉換,它可以與現(xiàn)有的字符串對象良好的結合。
Unicode針對現(xiàn)代和舊式的文本中所有的字符提供了一個序列。以前,字符只能使用256個序號,文本通常通過綁定代碼頁來與字符映射。這很容易導致混亂,特別是軟件的國際化(internationalization--通常寫做“i18n”--“i”+18 characters +“n”)。Unicode通過為所有字符定義一個統(tǒng)一的代碼頁解決了這個問題。
Python中定義一個Unicode字符串和定義一個普通字符串一樣簡單:
>;>;>; u'Hello World !'
u'Hello World !'
引號前小寫的“u”表示這里創(chuàng)建的是一個Unicode字符串。如果你想加入一個特殊字符,可以使用Python的 Unicode-Escape 編碼。如下例所示:
>;>;>; u'Hello\u0020World !'
u'Hello World !'
被替換的 \u0020 標識表示在給定位置插入編碼值為 0x0020 的 Unicode字符(空格符)。
其它字符也會被直接解釋成對應的Unicode碼。如果你有一個在西方國家常用的Latin-1編碼字符串,你可以發(fā)現(xiàn)Unicode字符集的前256個字符與Lation-1的對應字符編碼完全相同。
另外,有一種與普通字符串相同的行模式。想要使用Python的Raw-Unicode-Escape 編碼,你需要在字符串的引號前加上 ur 前綴。如果在小寫“u”前可能有不止一個反斜杠,它只會把那些單獨的 \uXXXX 轉化為Unicode字符。
>;>;>; ur'Hello\u0020World !'
u'Hello World !'
>;>;>; ur'Hello\\u0020World !'
u'Hello\\\\u0020World !'
行模式在你需要輸入很多個反斜杠時很有用,可能會用于正規(guī)表達式。
作為這些編碼標準的一部分,Python提供了一個完備的方法集用于從已知的編碼集創(chuàng)建Unicode字符串。
內置函數(shù)unicode() 提供了訪問(編碼和解碼)所有已注冊的Unicode編碼的方法。它能轉換眾所周知的 Latin-1, ASCII, UTF-8, 和 UTF-16。后面的兩個可變長編碼字符集用一個或多個byte存儲Unicode字符。默認的字符集是 ASCII ,它只處理0到127的編碼,拒絕其它的字符并返回一個錯誤。當一個Unicode字符串被打印、寫入文件或通過str()轉化時,它們被替換為默認的編碼。
>;>;>; u"abc"
u'abc'
>;>;>; str(u"abc"
'abc'
>;>;>; u"&&ü"
u'\xe4\xf6\xfc'
>;>;>; str(u"&&ü"
Traceback (most recent call last):
File "<stdin>;", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(12
要把一個Unicode字符串用指定的字符集轉化成8位字符串,可以使用Unicode對象提供的encode()方法,它有一個參數(shù)用以指定編碼名稱。編碼名稱小寫。
>;>;>; u"&&ü".encode('utf-8')
'\xc3\xa4\xc3\xb6\xc3\xbc'
如果你有一個特定編碼的字符串,想要把它轉為Unicode字符集,,可以使用uncode()函數(shù),它以編碼名做為第二個參數(shù)。
>;>;>; unicode('\xc3\xa4\xc3\xb6\xc3\xbc', 'utf-8')
u'\xe4\xf6\xfc'
3.1.4 鏈表
Python 已經有了幾個復合數(shù)據(jù)類型,用于組織其它的值。最通用的是鏈表,它寫為中括之間用逗號分隔的一列值(子項),鏈表的子項不一定是同一類型的值。
>;>;>; a = ['spam', 'eggs', 100, 1234]
>;>;>; a
['spam', 'eggs', 100, 1234]
像字符串一樣,鏈表也以零開始,可以被切片,聯(lián)接,等等:
>;>;>; a[0]
'spam'
>;>;>; a[3]
1234
>;>;>; a[-2]
100
>;>;>; a[1:-1]
['eggs', 100]
>;>;>; a[] + ['bacon', 2*2]
['spam', 'eggs', 'bacon', 4]
>;>;>; 3*a[] + ['Boe!']
['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boe!']
與不變的字符串不同,鏈表可以改變每個獨立元素的值:
>;>;>; a
['spam', 'eggs', 100, 1234]
>;>;>; a[2] = a[2] + 23
>;>;>; a
['spam', 'eggs', 123, 1234]
可以進行切片操作,甚至還可以改變鏈表的大。
>;>;>; # Replace some items:
... a[0] = [1, 12]
>;>;>; a
[1, 12, 123, 1234]
>;>;>; # Remove some:
... a[0] = []
>;>;>; a
[123, 1234]
>;>;>; # Insert some:
... a[1] = ['bletch', 'xyzzy']
>;>;>; a
[123, 'bletch', 'xyzzy', 1234]
>;>;>; a[] = a # Insert (a copy of) itself at the beginning
>;>;>; a
[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234]
內置函數(shù)len()也同樣可以用于鏈表:
>;>;>; len(a)
8
它也可以嵌套鏈表(在鏈表中創(chuàng)建其它鏈表),例如:
>;>;>; 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實際上指向同一個對象!我們在后面會講到對象語法。
3.2 開始編程
當然,我們可以用Python做比2加2更復雜的事。例如,我們可以用以下的方法輸出菲波那契(Fibonacci)序列的子序列:
>;>;>; # 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
示例中介紹了一些新功能:
第一行包括了復合參數(shù):變量a和b同時被賦值為0和1。最后一行又一次使用了這種技術,證明了在賦值之前表達式右邊先進行了運算。右邊的表達式從左到右運算。
while循環(huán)運行在條件為真時執(zhí)行。在Python中,類似于C任何非零值為真,零為假。 這個條件也可以用于字符串或鏈表,事實上于對任何序列類型,長度非零時為真,空序列為假。示例所用的是一個簡單的比較。標準的比較運算符寫法和C相同: < (小于),>; (大于),== (等于),<= (小于等于),>;=(大于等于)和!= (不等于)。
循環(huán)體是縮進的:縮進是Python對語句分組的方法。 Python仍沒有提供一個智能編輯功能所以你要在每一個縮進行輸入一個tab或(一個或多個)空格。 實際上你可能會準備更為復雜的文本編輯器來編寫你的Python程序,大多數(shù)文本編輯器都提供了自動縮進功能。交互式的輸入一個復雜語句時,需要用一個空行表示完成(因為解釋器沒辦法猜出你什么時候輸入最后一行)。需要注意的是每一行都要有相同的空字符來標識這是同一個語句塊。
print語句打印給定表達式的值。它與你僅僅輸入你需要的表達式(就像前面的計算器示例)不同,它可以同時輸出多個表達式。字符串輸出時沒有引號,各項之間用一個空格分開,你可以很容易區(qū)分它們,如下所示:
>;>;>; 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
需要注意的是,如果最后一行仍沒有寫完,解釋器會在它打印下一個命令時插入一個新行。 |
|