### 3. Python簡介
以下的示例中,輸入和輸出通過是否存在提示符([*>>>*](#)和[*...*](#))來區分:如果要重復該示例,你必須在提示符出現后,輸入提示符后面的所有內容;沒有以提示符開頭的行是解釋器的輸出。注意示例中出現從提示符意味著你一定要在最后加上一個空行;這用于結束一個多行命令。
本手冊中的很多示例,甚至在交互方式下輸入的示例,都帶有注釋。Python中的注釋以哈希字符#開始,直至實際的行尾。注釋可以從行首開始,也可以跟在空白或代碼之后,但不能包含在字符串字面量中。字符串字面量中的#字符僅僅表示#。因為注釋只是為了解釋代碼并且不會被Python解釋器解釋,所以敲入示例的時候可以忽略它們。
例如:
~~~
# this is the first comment
spam = 1 # and this is the second comment
# ... and now a third!
text = "# This is not a comment because it's inside quotes."
~~~
### 3.1. 用Python作為計算器
讓我們嘗試一些簡單的Python命令。啟動解釋器然后等待主提示符 >>>。(應該不需要很久。)
#### 3.1.1. 數字
解釋器可作為一個簡單的計算器:你可以向它輸入一個表達式,它將返回其結果。表達式語法很直白:運算符+、-、*和/的用法就和其它大部分語言一樣(例如Pascal或C);括號(())可以用來分組。例如:
~~~
>>> 2 + 2
4
>>> 50 - 5*6
20
>>> (50 - 5.0*6) / 4
5.0
>>> 8 / 5.0
1.6
~~~
整數(例如2,4,20)的類型是[int](# "int"),帶有小數部分的數字(例如5.0, 1.6)的類型是[float](# "float")。在本教程的后面我們會看到更多關于數字類型的內容。
除法(/)返回的類型取決于它的操作數。如果兩個操作數都是[int](# "int"),將采用[*floor除法(floor division)*](#)并返回一個[int](# "int")。如果兩個操作數中有一個是[float](# "float"),將采用傳統的除法并返回一個[float](# "float")。還提供//運算符用于floor division 而無論操作數是什么類型。余數可以用%操作符計算:
~~~
>>> 17 / 3 # int / int -> int
5
>>> 17 / 3.0 # int / float -> float
5.666666666666667
>>> 17 // 3.0 # explicit floor division discards the fractional part
5.0
>>> 17 % 3 # the % operator returns the remainder of the division
2
>>> 5 * 3 + 2 # result * divisor + remainder
17
~~~
通過Python,還可以使用**運算符計算冪乘方[[1]](#):
~~~
>>> 5 ** 2 # 5 squared
25
>>> 2 ** 7 # 2 to the power of 7
128
~~~
等號(=)用于給變量賦值。賦值之后,在下一個提示符之前不會有任何結果顯示:
~~~
>>> width = 20
>>> height = 5*9
>>> width * height
900
~~~
如果變量沒有“定義”(賦值),使用的時候將會報錯:
~~~
>>> n # try to access an undefined variable
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'n' is not defined
~~~
Python中完全支持浮點數;整數和浮點數的混合計算中,整數會被轉換為浮點數:
~~~
>>> 3 * 3.75 / 1.5
7.5
>>> 7.0 / 2
3.5
~~~
在交互模式下,最近一次表達式的值被賦給變量_。這意味著把Python當做桌面計算器使用的時候,可以方便的進行連續計算,例如:
~~~
>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06
~~~
用戶應該將這個變量視為只讀的。不要試圖去給它賦值 — 你將會創建出一個獨立的同名局部變量,并且屏蔽了內置變量的魔術效果。
除了[int](# "int")和[float](# "float"),Python還支持其它數字類型,例如[Decimal](# "decimal.Decimal")and[Fraction](# "fractions.Fraction")。Python還內建支持[*復數*](#),使用后綴j或J表示虛數部分(例如3+5j)。
#### 3.1.2. 字符串
除了數值,Python 還可以操作字符串,可以用幾種方法來表示。它們可以用單引號('...')或雙引號("...")括起來,效果是一樣的[[2]](#)。\可以用來轉義引號。
~~~
>>> 'spam eggs' # single quotes
'spam eggs'
>>> 'doesn\'t' # use \' to escape the single quote...
"doesn't"
>>> "doesn't" # ...or use double quotes instead
"doesn't"
>>> '"Yes," he said.'
'"Yes," he said.'
>>> "\"Yes,\" he said."
'"Yes," he said.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
~~~
在交互式解釋器中,輸出的字符串會用引號引起來,特殊字符會用反斜杠轉義。雖然可能和輸入看上去不太一樣,但是兩個字符串是相等的。如果字符串中只有單引號而沒有雙引號,就用雙引號引用,否則用單引號引用。
~~~
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
>>> print '"Isn\'t," she said.'
"Isn't," she said.
>>> s = 'First line.\nSecond line.' # \n means newline
>>> s # without print(), \n is included in the output
'First line.\nSecond line.'
>>> print s # with print, \n produces a new line
First line.
Second line.
~~~
如果你前面帶有\的字符被當作特殊字符,你可以使用*原始字符串*,方法是在第一個引號前面加上一個r:
~~~
>>> print 'C:\some\name' # here \n means newline!
C:\some
ame
>>> print r'C:\some\name' # note the r before the quote
C:\some\name
~~~
字符串可以跨多行。一種方法是使用三引號:"""..."""或者'''...'''。行尾換行符會被自動包含到字符串中,但是可以在行尾加上\來避免這個行為。下面的示例:
~~~
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
~~~
字符串可以用+操作符連接,也可以用*操作符重復多次:
~~~
>>> # 3 times 'un', followed by 'ium'
>>> 3 * 'un' + 'ium'
'unununium'
~~~
相鄰的兩個或多個*字符串字面量*(用引號引起來的)會自動連接。
~~~
>>> 'Py' 'thon'
'Python'
~~~
然而這種方式只對兩個字面量有效,變量或者表達式是不行的。
~~~
>>> prefix = 'Py'
>>> prefix 'thon' # can't concatenate a variable and a string literal
...
SyntaxError: invalid syntax
>>> ('un' * 3) 'ium'
...
SyntaxError: invalid syntax
~~~
如果你想連接多個變量或者連接一個變量和一個字面量,使用+:
~~~
>>> prefix + 'thon'
'Python'
~~~
這個功能在你想切分很長的字符串的時候特別有用:
~~~
>>> text = ('Put several strings within parentheses '
'to have them joined together.')
>>> text
'Put several strings within parentheses to have them joined together.'
~~~
字符串可以*索引*,第一個字符的索引值為0。Python沒有單獨的字符類型;一個字符就是一個簡單的長度為1的字符串。
~~~
>>> word = 'Python'
>>> word[0] # character in position 0
'P'
>>> word[5] # character in position 5
'n'
~~~
索引也可以是負值,此時從右側開始計數:
~~~
>>> word[-1] # last character
'n'
>>> word[-2] # second-last character
'o'
>>> word[-6]
'P'
~~~
注意,因為-0和0是一樣的,負的索引從-1開始。
除了索引,還支持*切片*。索引用于獲得單個字符,*切片*讓你獲得一個子字符串。
~~~
>>> word[0:2] # characters from position 0 (included) to 2 (excluded)
'Py'
>>> word[2:5] # characters from position 2 (included) to 5 (excluded)
'tho'
~~~
注意,包含起始的字符,不包含末尾的字符。這使得s[:i]+s[i:]永遠等于s:
~~~
>>> word[:2] + word[2:]
'Python'
>>> word[:4] + word[4:]
'Python'
~~~
切片的索引有非常有用的默認值;省略的第一個索引默認為零,省略的第二個索引默認為切片的字符串的大小。
~~~
>>> word[:2] # character from the beginning to position 2 (excluded)
'Py'
>>> word[4:] # characters from position 4 (included) to the end
'on'
>>> word[-2:] # characters from the second-last (included) to the end
'on'
~~~
有個方法可以記住切片的工作方式,把索引當做字符*之間*的點,第一個字符的左邊是0。含有*n*個字符的字符串的最后一個字符的右邊是索引*n*,例如:
~~~
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
~~~
第一行給出了字符串中0..6各索引的位置;第二行給出了相應的負索引。從*i*到*j*的切片由*i*和*j*之間的所有字符組成。
對于非負索引,如果上下都在邊界內,切片長度就是兩個索引之差。例如,word[1:3] 的長度是 2。
試圖使用太大的索引會導致錯誤:
~~~
>>> word[42] # the word only has 7 characters
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
~~~
但是,當用于切片時,超出范圍的切片索引會被優雅地處理:
~~~
>>> word[4:42]
'on'
>>> word[42:]
''
~~~
Python字符串不可以被更改 — 它們是[*不可變的*](#)。因此,賦值給字符串索引的位置會導致錯誤:
~~~
>>> word[0] = 'J'
...
TypeError: 'str' object does not support item assignment
>>> word[2:] = 'py'
...
TypeError: 'str' object does not support item assignment
~~~
如果你需要一個不同的字符串,你應該創建一個新的:
~~~
>>> 'J' + word[1:]
'Jython'
>>> word[:2] + 'py'
'Pypy'
~~~
內置函數[len()](# "len")返回字符串的長度:
~~~
>>> s = 'supercalifragilisticexpialidocious'
>>> len(s)
34
~~~
請參閱
[*序列類型 — str, unicode, list, tuple, bytearray, buffer, xrange*](#)字符串和下節描述的Unicode字符串是*序列類型*的例子,它們支持這種類型共同的操作。[*字符串方法*](#)字符串和Unicode字符串都支持大量的方法用于基本的轉換和查找。[*字符串格式化*](#)這里描述了使用[str.format()](# "str.format")進行字符串格式化的信息。[*字符串格式化操作*](#)這里描述了舊式的字符串格式化操作,它們在字符串和Unicode字符串是%操作符的左操作數時調用。
#### 3.1.3. Unicode 字符串
從Python2.0開始,程序員們有了一個新的用來存儲文本數據的類型:Unicode對象。它可以用來存儲和處理Unicode數據(見[http://www.unicode.org/](http://www.unicode.org/)),并與現有的字符串對象有良好的集成,必要時提供自動轉換。
Unicode 的優點在于為現代和古代的每一種文字的每一個字符提供了統一的序號。以前,腳本只有256個可用的字符編碼。通常,文本被綁定到映射字符編碼的代碼頁上。這帶來很多麻煩,尤其是軟件國際化(通常寫成i18n — 'i' + 18個字符 + 'n')。Unicode 為所有腳本定義一個代碼頁,從而解決了這些問題。
在Python中創建Unicode字符串和創建普通字符串一樣簡單:
~~~
>>> u'Hello World !'
u'Hello World !'
~~~
引號前面小寫的'u'表示創建一個Unicode字符串。如果你想要在字符串中包含特殊字符,你可以通過使用Python的*Unicode轉義*編碼。下面的示例演示如何使用:
~~~
>>> u'Hello\u0020World !'
u'Hello World !'
~~~
轉義序列u0020表示在給定位置插入序號值為0x0020(空格字符)的Unicode字符。
其他字符就像 Unicode 編碼一樣被直接解釋為對應的編碼值。如果你有使用在許多西方國家使用的標準Latin-1編碼的字符串,你會發現編碼小于256的Unicode字符和在Latin-1編碼中的一樣。
和普通字符串一樣,Unicode字符串也有raw模式。要使用*Raw-Unicode-Escape*編碼,必須在引號的前面加上'ur'。只有在小寫的'u'前面有奇數個反斜杠,才會用上面的uXXXX 轉換
~~~
>>> ur'Hello\u0020World !'
u'Hello World !'
>>> ur'Hello\\u0020World !'
u'Hello\\\\u0020World !'
~~~
當你需要輸入很多反斜杠時,raw 模式非常有用,這在正則表達式中幾乎是必須的。
除了這些標準的編碼,Python提供了基于已知編碼來創建Unicode字符串的一整套方法。
內置函數[unicode()](# "unicode")提供對所有已注冊的Unicode編解碼器(編碼和解碼)的訪問。這些編解碼器可以轉換的比較有名的編碼有*Latin-1*、*ASCII*、*UTF-8*和*UTF-16*。后兩個是可變長度編碼,它們存儲每個Unicode字符在一個或多個字節中。默認編碼通常設置為ASCII,此編碼接受0到127這個范圍的編碼,否則報錯。當打印、向文件寫入、或者用[str()](# "str")轉換一個Unicode字符串時,轉換將使用默認編碼。
~~~
>>> 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(128)
~~~
Unicode對象提供encode()方法將Unicode字符串轉換為使用指定編碼的8位字符串,它接收一個編碼名稱作為參數。編碼名應該小寫。
~~~
>>> u"??ü".encode('utf-8')
'\xc3\xa4\xc3\xb6\xc3\xbc'
~~~
如果有一個已知編碼的數據,希望從它生成一個Unicode字符串,你可以使用[unicode()](# "unicode")函數并以編碼名作為第二個參數。
~~~
>>> unicode('\xc3\xa4\xc3\xb6\xc3\xbc', 'utf-8')
u'\xe4\xf6\xfc'
~~~
#### 3.1.4. 列表
Python有幾個*復合*數據類型,用來組合其他的值。最有用的是*列表*,可以寫成中括號中的一列用逗號分隔的值。列表可以包含不同類型的元素,但是通常所有的元素都具有相同的類型。
~~~
>>> squares = [1, 4, 9, 16, 25]
>>> squares
[1, 4, 9, 16, 25]
~~~
和字符串(以及其它所有內建的[*序列*](#)類型)一樣,列表可以索引和切片:
~~~
>>> squares[0] # indexing returns the item
1
>>> squares[-1]
25
>>> squares[-3:] # slicing returns a new list
[9, 16, 25]
~~~
所有的切片操作都會返回一個包含請求的元素的新列表。這意味著下面的切片操作返回列表一個新的(淺)拷貝副本。
~~~
>>> squares[:]
[1, 4, 9, 16, 25]
~~~
列表也支持連接這樣的操作:
~~~
>>> squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
~~~
與字符串的[*不可變*](#)特性不同,列表是[*可變的*](#)類型,例如可以改變它們的內容:
~~~
>>> cubes = [1, 8, 27, 65, 125] # something's wrong here
>>> 4 ** 3 # the cube of 4 is 64, not 65!
64
>>> cubes[3] = 64 # replace the wrong value
>>> cubes
[1, 8, 27, 64, 125]
~~~
你還可以使用append()*方法*(后面我們會看到更多關于方法的內容)在列表的末尾添加新的元素:
~~~
>>> cubes.append(216) # add the cube of 6
>>> cubes.append(7 ** 3) # and the cube of 7
>>> cubes
[1, 8, 27, 64, 125, 216, 343]
~~~
給切片賦值也是可以的,此操作甚至可以改變列表的大小或者清空它::
~~~
>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> # replace some values
>>> letters[2:5] = ['C', 'D', 'E']
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
>>> # now remove them
>>> letters[2:5] = []
>>> letters
['a', 'b', 'f', 'g']
>>> # clear the list by replacing all the elements with an empty list
>>> letters[:] = []
>>> letters
[]
~~~
內置函數[len()](# "len")也適用于列表:
~~~
>>> letters = ['a', 'b', 'c', 'd']
>>> len(letters)
4
~~~
列表可以嵌套(創建包含其他列表的列表),例如:
~~~
>>> a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'
~~~
### 3.2. 編程第一步
當然,我們可以將Python用于比計算2加2更復雜的任務。例如,我們可以寫一個生成*斐波那契*初始子序列的程序,如下所示:
~~~
>>> # 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。最后一行又這樣使用了一次,說明等號右邊的表達式在賦值之前首先被完全解析。右側表達式是從左到右計算的。
-
只要條件(這里是 b<10)為真,[while](#)循環反復執行。在Python中,和C一樣,任何非零整數值都為真;零為假。循環條件也可以是一個字符串或者列表,實際上可以是任何序列;長度不為零的序列為真,空序列為假。示例中使用的測試是一個簡單的比較。標準比較運算符與 C 的寫法一樣:<(小于),>(大于),==(等于),<=(小于或等于),>=(大于或等于)和!=(不等于)。
-
循環*體*是*縮進* 的:縮進是Python分組語句的方式。交互式輸入時,你必須為每個縮進的行輸入一個 tab 或(多個)空格。實踐中你會用文本編輯器來編寫復雜的 Python 程序;所有說得過去的文本編輯器都有自動縮進的功能。交互式輸入復合語句時,最后必須在跟隨一個空行來表示結束(因為解析器無法猜測你什么時候已經輸入最后一行)。注意基本塊內的每一行必須按相同的量縮進。
-
[print](#)語句輸出傳給它的表達式的值。與僅僅輸出你想輸出的表達式不同(就像我們在前面計算器的例子中所做的),它可以輸出多個表達式和字符串。打印出來的字符串不包含引號,項目之間會插入一個空格,所以你可以設置漂亮的格式,像這樣:
~~~
>>> i = 256*256
>>> print 'The value of i is', i
The value of i is 65536
~~~
尾部的逗號可以避免輸出換行符:
~~~
>>> 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
~~~
注意,如果最后一行沒有結束,解釋器會插入一個新行(在打印下一個提示符之前)。
腳注
| [[1]](#) | 因為**的優先級高于-,所以-3**2將解釋為-(3**2)且結果為-9。為了避免這點并得到9,你可以使用(-3)**2。 |
|-----|-----|
| [[2]](#) | 與其它語言不同,特殊字符例如\n在單引號('...')和雙引號("...")中具有相同的含義。兩者唯一的區別是在單引號中,你不需要轉義"(但你必須轉義\'),反之亦然。 |
|-----|-----|
- Python 2 教程
- 1. 吊吊你的胃口
- 2. Python 解釋器
- 3. Python簡介
- 4. 控制流
- 5. 數據結構
- 6. 模塊
- 7. 輸入和輸出
- 8. 錯誤和異常
- 9. 類
- 10. 標準庫概覽
- 11. 標準庫概覽 — 第II部分
- 12.現在怎么辦?
- 13. 交互式輸入的編輯和歷史記錄
- 14. 浮點數運算:問題和局限
- Python 2 標準庫
- 1. 引言
- 2. 內建函數
- 3. 不太重要的內建函數
- 4. 內建的常量
- 5. 內建的類型
- 6. 內建的異常
- 7. String Services
- 8. Data Types
- 9. Numeric and Mathematical Modules
- 10. File and Directory Access
- 11. Data Persistence
- 13. File Formats
- 14. Cryptographic Services
- 15. Generic Operating System Services
- 16. Optional Operating System Services
- 17. Interprocess Communication and Networking
- 18. Internet Data Handling
- 20. Internet Protocols and Support
- 26. Debugging and Profiling
- 28. Python Runtime Services
- Python 2 語言參考
- 1. 簡介
- 2. 詞法分析
- 3. 數據模型
- 4. 執行模型
- 5. 表達式
- 6. 簡單語句
- 7. 復合語句
- 8. 頂層的組件
- 9. 完整的語法規范
- Python 3 教程
- 1. 引言
- 2. Python 解釋器
- 3. Python簡介
- 4. 控制流
- 5. 數據結構
- 6. 模塊
- 7. 輸入和輸出
- 8. 錯誤和異常
- 9. 類
- 10. 標準庫概覽
- 11. 標準庫概覽 — 第II部分
- 12.現在怎么辦?
- 13. 交互式輸入的編輯和歷史記錄
- 14. 浮點數運算:問題和局限