程式扎記: [ Python 文章收集 ] Python 3 初探,第 1 部分: Python 3 的新特性

標籤

2012年12月2日 星期日

[ Python 文章收集 ] Python 3 初探,第 1 部分: Python 3 的新特性


來源自 這裡
Preface:
Python 3是Guido van Rossum功能強大的通用編程語言的最新版本。它雖然打破了與2.x版本的向後兼容性,但卻清理了某些語法方面的問題。本文是系列文章中的第一篇,介紹了影響該語言及向後兼容性的各種變化,並且還提供了新特性的幾個例子.

Python版本3,也被稱為Python 3000或Py3K(仿效Microsoft® Windows® 2000操作系統而命名的暱稱)是Guido van Rossum通用編程語言的最新版本。雖然新版本對該核心語言做了很多改進,但還是打破了與2.x版本的向後兼容性。其他一些變化則是人們期待已久的,比如:
* 真正的除法—例如,1/2返回的是.5。
* long 和 int 類型被統一為一種類型,刪除了後綴L。
* True、False和 None現在都是關鍵字

本文— Python 3系列文章中的第一篇—的內容涵蓋了新的print()函數、input()、輸入/輸出(I/O)的變化、新的 bytes數據類型、字符串和字符串格式化的變化以及內置的 dict類型的變化。本文面向的是那些熟悉Python並對新版本的變化很感興趣但又不想費力讀完所有 Python Enhancement Proposal(PEP)的編程人員。(本文後面的參考資料部分提供了有關這些PEP的鏈接。

新的 print() 函數:
如今,您將需要讓手指習慣於鍵入 print("hello"),而不是原來的 print "hello"這是因為 print現在是一個函數,不再是一個語句. 我知道,這多少有點痛苦。我認識的每個Python程序員—一旦安裝了版本3並得到“語法不正確”錯誤—都會鬱悶地大叫。我知道這兩個額外的符號十分討厭;我也知道這將會破壞向後兼容性。但是這種改變還是有好處的.

讓我們考慮這樣的情況,即需要將標準輸出(stdout)重定向到一個日誌。如下的例子會打開文件 log.txt 以便進行追加並將對象指定給 fid。之後,利用 print>>將一個字符串重定向給文件 fid:
>>> fid = open("log.txt", "a")
>>> print>>fid, "log text"

另外一個例子是重定向給標準錯誤(sys.stderr):
>>> print>>sys.stderr, "an error occurred"

上述兩個例子都不錯,但還有更好的解決方案。新的語法只要求給 print() 函數的關鍵字參數 file 傳遞一個值就可以了。比如:
>>> fid = open("log.txt", "a")
>>> print("log.txt", file=fid)

這樣的代碼,語法更為清晰。另一個好處是通過向 sep 關鍵字參數傳遞一個字符串就能更改分割符(separator),通過向 end 關鍵字參數傳遞另外一個字符串就能更改結束字符串。要更改分割符,可以利用
>>> print("Foo", "Bar", sep="%")
Foo%Bar

總地來說,新的語法為:
print([object, ...][, sep=' '][, end='endline_character_here'][, file=redirect_to_here])

其中,方括號([])內的代碼是可選的。默認地,若只調用print()自身,結果會追加一個換行符(\n).

從 raw_input() 到 input():
在 Python 版本2.x中,raw_input() 會從標準輸入(sys.stdin)讀取一個輸入並返回一個字符串,且尾部的換行符從末尾移除。下面的這個例子使用 raw_input()從命令提示符獲取一個字符串,然後將值賦給 quest:
>>> quest = raw_input("What is your quest? ")
What is your quest? To seek the holy grail.
>>> quest
'To seek the holy grail.'

與之不同,Python 2.x中的 input() 函數需要的是一個有效的Python表達式,比如3+5:

最初,曾有人建議將 input() 和 raw_input() 從 Python 內置的名稱空間一併刪除,因此就需要進行導入來獲得輸入能力。這從方法上就不對;因為,簡單鍵入:
>>> quest = input("What is your quest?")

將會變為:
>>> import sys
>>> print("What is your quest?")
>>> quest = sys.stdin.readline()

對於一個簡單輸入而言,這太過繁瑣,並且對於一個新手,這未免太難理解。往往需要向他們講述 模塊 和 導入 究竟是怎麼回事、字符串輸出以及句點操作符又是如何工作的(如此麻煩的話,與Java™語言就沒什麼差別了)。所以,在 Python 3 內,將 raw_input() 重命名為 input(),這樣一來,無須導入也能從標準輸入獲得數據了。如果您需要保留版本2.x的 input() 功能,可以使用eval(input()),效果基本相同.

有關 bytes 的簡介:
新的數據類型 bytes literal 及 bytes 對象的用途是存儲二進制數據。此對像是 0 到 127 的不可修改的整數序列或純粹的ASCII字符。實際上,它是版本2.5中 bytearray 對象的不可修改版本。一個 bytes literal 是一個前面冠以 b 的字符串—例如,b'byte literal'。對 bytes literal 的計算會生成一個新的 bytes 對象。可以用 bytes() 函數創建一個新的 bytes 對象。bytes 對象的構造函數為:
bytes([initializer[, encoding]])

例如:
>>> b = (b'\xc3\x9f\x65\x74\x61')
>>> b
b'\xc3\x9feta'

會創建一個bytes對象,但這是多餘的,因為通過賦值一個byte literal就完全可以創建bytes對象。(我只是想要說明這麼做是可行的,但是我並不建議您這麼做。)如果您想要使用 iso-8859-1 編碼,可以嘗試下面的做法:
>>> b = bytes('\xc3\x9f\x65\x74\x61', 'iso-8859-1')
>>> b
b'\xc3\x9feta'

如果初始化器(initializer)是一個字符串,那麼就必須提供一種編碼。如果初始化器是一個bytes literal,則無須指定編碼類型:請記住,bytes literal 並不是字符串。但是與字符串相似,可以連接多個字節:
>>> b'hello' b' world'
b'hello world'

用bytes()方法代表二進制數據以及被編碼的文本。要將 bytes轉變為str, bytes對象必須要進行解碼(稍後會詳細介紹)。二進制數據用 decode()方法編碼。例如:
>>> b'\xc3\x9f\x65\x74\x61'.decode()
'ßeta'

字符串:
Python具有單一的字符串類型str,其功能類似於版本2.x的unicode類型。換言之,所有字符串都是unicode字符串。而且—對非拉丁文的文本用戶也非常方便—非-ASCII標識符現在也是允許的。例如:
>>> césar = ["author", "consultant"]
>>> print(césar)
['author', 'consultant']

在Python之前的版本內,repr() 方法會將8-位字符串轉變為ASCII。例如:
>>> repr('é')
"'\\xc3\\xa9'"

現在,它會返回一個unicode 字符串:
>>> repr('é')
"'e'"

字符串對象和字節對像是不兼容的。如果想要得到字節的字符串表示,需要使用它的 decode() 方法。相反,如果想要從該字符串得到bytes literal表示,可以使用字符串對象的 encode()方法

字符串格式化方面的變化:
很多Python程序員都感覺用來格式化字符串的這個內置的 % 操作符太有限了,這是因為:
* 它是一個二進制的操作符,最多只能接受兩個參數
* 除了格式化字符串參數,所有其他的參數都必須用一個元組(tuple)或是一個字典(dictionary)進行擠壓

這種格式化多少有些不靈活,所以 Python 3 引入了一種新的進行字符串格式化的方式(版本3保留了%操作符和string.Template模塊)。字符串對象現在均具有一個方法 format(),此方法接受位置參數和關鍵字參數,二者均傳遞到 replacement 字段。Replacement 字段在字符串內由花括號({})標示。replacement字段內的元素被簡單稱為一個字段。以下是一個簡單的例子:
>>> "I love {0}, {1}, and {2}".format("eggs", "bacon", "sausage")
'I love eggs, bacon, and sausage'

字段{0}、{1}和{2}通過位置參數eggs、 bacon 和 sausage 被傳遞給 format() 方法。如下的例子顯示瞭如何使用 format() 通過關鍵字參數的傳遞來進行格式化:
>>> "I love {a}, {b}, and {c}".format(a="eggs", b="bacon", c="sausage")
'I love eggs, bacon, and sausage'

請記住,在關鍵字參數之後放置非關鍵字參數是一種語法錯誤。要想轉義花括號,只需使用雙倍的花括號,如下所示:
>>> "{{0}}".format("can't see me")
'{0}'

新的 format() 內置函數可以格式化單個值。比如:
>>> print(format(10.0, "7.3g"))

換言之,g 代表的是一般格式,它輸出的是寬度固定的值。小數點前的第一個數值指定的是最小寬度,小數點後的數值指定的是精度.

內置dict 類型的變化:
3.0內的另一個重大改變是字典內 dict.iterkeys()、 dict.itervalues()和 dict.iteritems()方法的刪除。取而代之的是.keys()、 .values()和 .items(),它們被進行了修補,可以返回輕量的、類似於集的容器對象,而不是鍵和值的列表。這樣的好處是在不進行鍵和條目複製的情況下,就能在其上執行set操作。例如:
>>> d = {1:"dead", 2:"parrot"}
>>> print(d.items())
dict_items([(1, 'dead'), (2, 'parrot')])

這裡,我創建了具有兩個鍵和值的一個字典,然後輸出了d.items()的值,返回的是一個對象,而不是值的列表。可以像set對像那樣測試某個元素的成員資格,比如:
>>> 1 in d # test for membership
True

如果您的確想要得到值的列表,可以對所返回的dict對象進行強制類型轉換。比如:
>>> keys = list(d.keys())
>>> keys
[1, 2]

新的I/O:
打開一個流需要使用內置的 open(fileName) 函數,但是也可以調用 io.open(fileName))。這麼做會返回一個緩衝了的文本文件;read() 和 readline() 會返回字符串(請注意,Python 3內的所有字符串都是unicode)。您也可以使用 open(fileName, 'b') 打開一個緩衝了的二進製文件。在這種情況下,read() 會返回字節,但 readline() 則不能用.

此內置 open() 函數的構造函數是:
open(file,mode="r",buffering=None,encoding=None,errors=None,newline=None,closefd=True)

可能的模式有:
* r:
* w:打開供寫入
* a:打開供追加
* b:二進制模式
* t:文本模式
* +:打開一個磁盤文件供更新
* U:通用換行模式

默認的模式是 rt,即打開供讀取的文本模式. buffering 關鍵字參數的期望值是以下三個整數中的一個以決定緩衝策略:
* 0:關閉緩衝
* 1:行緩衝
* > 1:完全緩衝(默認)

open() 返回的對象取決於您所設置的模式。表1給出了返回類型:


底下為打開一個緩衝了的二進制流以供讀取的範例:
>>> f = io.open("singleThd.py", "rb")
>>> f
<_io .bufferedreader=".bufferedreader" name="singleThd.py">
>>> f.close()

BufferedReader對象可以訪問很多有用的方法,比如isatty、 peek、raw、 readinto、readline、 readlines、seek、 seekable、tell、 writable、write和 writelines。要想查看完整列表,可以在BufferedReader對像上運行dir()

參考資料:
PEP 3111:Simple input built-in in Python 3000
PEP 3116:New I/O
PEP 3138:String representation in Python 3000
PEP 3112:Bytes literals in Python 3000
PEP 3137:Immutable Bytes and Mutable Buffer
PEP 3106:Revamping dict.keys(), .values() & .items()
PEP 3108:Standard Library Reorganization
PEP 3100:Miscellaneous Python 3.0 Plans
This message was edited 16 times. Last update was at 03/12/2012 13:20:13

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!