【python】Python 3 的新特性

楊奇龍發表於2011-07-24
print() 函式
如今,您將需要讓手指習慣於鍵入 print(“hello”),而不是原來的 print “hello”,這是因為print 現在是一個函式,不再是一個語句讓我們考慮這樣的情況,即需要將標準輸出(stdout)重定向到一個日誌。
新的語法只要求給 print() 函式的關鍵字引數 file 傳遞一個值就可以了,比如:
fid = open(“log.txt”, “a”)
print(“log.txt”, file=fid)
這樣的程式碼,語法更為清晰。另一個好處是透過向 sep 關鍵字引數傳遞一個字串就能更改分割符(separator),透過向 end 關鍵字引數傳遞另外一個字串就能更改結束字串。要更改分割符,可以利用:
print(“Foo”, “Bar”, sep=”%”)
總地來說,新的語法為:
print([object, ...][, sep=' '][, end='endline_character_here'][,
file=redirect_to_here])
其中,方括號([])內的程式碼是可選的。預設地,若只呼叫 print() 自身,結果會追加一個換行符(\n)。
raw_input() 到 input()
在 Python 版本 2.x 中,raw_input() 會從標準輸入(sys.stdin)讀取一個輸入並返回一個字串,且尾部的換行符從末尾移除。在Python 2.x 版本 2.x 中, input() 函式需要的是一個有效的 Python 表示式。在 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’。對 bytesliteral 的計算會生成一個新的 bytes 物件。可以用 bytes() 函式建立一個新的 bytes 物件。
bytes 物件的建構函式為:bytes([initializer[, encoding]])
例如:
>>>b = (b’\xc3\x9f\x65\x74\x61′)
>>>print(b)
b’\xc3\x83\xc2\x9feta’
會建立一個 bytes 物件,但這是多餘的,因為透過賦值一個 byte literal 就完全可以建立 bytes 物件。(我只是想要說明這麼做是可行的,但是我並不建議您這麼做。)如果您想要使用 iso-8859-1 編碼,可以嘗試下面的做法:
>>>b = bytes(‘\xc3\x9f\x65\x74\x61′, ‘iso-8859-1′)
>>>print(b)
b’\xc3\x83\xc2\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’
也可以從檔案中直接讀取二進位制資料。請看以下的程式碼:
>>>data = open(‘dat.txt’, ‘rb’).read()
>>>print(data) # data is a string
>>># content of data.txt printed out here
它的功能是開啟檔案以便在二進位制模式內讀取一個檔案物件,並在整個檔案內進行讀取。
字串
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(‘é’)
“‘é’”
 
正如我之前提到的,這個字串是內建的字串型別。
字串物件和位元組物件是不相容的。如果想要得到位元組的字串表示,需要使用它的 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’
 
下面是另外一個綜合了位置引數和關鍵字引數的例子:
>>>”I love {0}, {1}, and {param}”.format(“eggs”, “bacon”, param=”sausage”)
‘I love eggs, bacon, and sausage’
 
請記住,在關鍵字引數之後放置非關鍵字引數是一種語法錯誤。要想轉義花括號,只需使用雙倍的花括號,如下所示:
>>>”{{0}}”.format(“can’t see me”)
‘{0}’
 
位置引數 can’t see me 沒有被輸出,這是因為沒有欄位可以輸出。請注意這不會產生錯誤。
新的 format() 內建函式可以格式化單個值。比如:
>>>print(format(10.0, “7.3g”))
       10
換言之,g 代表的是 一般格式,它輸出的是寬度固定的值。小數點前的第一個數值指定的是最小寬度,小數點後的數值指定的是精度。format specifier 的完整語法超出了本文的討論範圍,更多資訊,可以參見本文的 參考資料 小節。
內建 dict 型別的變化
3.0 內的另一個重大改變是字典內 dict.iterkeys()、 dict.itervalues() 和 dict.iteritems() 方法的刪除。取而代之的是.keys()、 .values() 和 .items(),它們被進行了修補,可以返回輕量的、類似於集的容器物件,而不是鍵和值的列表。這樣的好處是在不進行鍵和條目複製的情況下,就能在其上執行 set 操作。例如:
>>>d = {1:”dead”, 2:”parrot”}
>>>print(d.items())
 
注意:在 Python 內,集 是惟一元素的無序集合。
這裡,我建立了具有兩個鍵和值的一個字典,然後輸出了 d.items() 的值,返回的是一個物件,而不是值的列表。可以像 set 物件那樣測試某個元素的成員資格,比如:
>>>1 in d # test for membership
True
 
如下是在 dict_values 物件的條目上進行迭代的例子:
>>>for values in d.items():
…     print(values)
dead
parrot
 
不過,如果您的確想要得到值的列表,可以對所返回的 dict 物件進行強制型別轉換。比如:
>>>keys = list(d.keys())
>>>print(keys)
[1,2]
新的 I/O
ABC 是一些無法被例項化的類。要使用 ABC,子類必須繼承自此 ABC 並且還要覆蓋其抽象方法。如果方法的字首使用 @abstractmethod 修飾符(decorator),那麼此方法就是一個抽象方法。新的 ABC 框架還提供了 @abstractproperty 修飾符以便定義抽象屬性。可以透過匯入標準庫模組 abc 來訪問這個新框架。清單 1 所示的是一個簡單的例子。
清單 1. 一個簡單的抽象基類
    
from abc import ABCMeta
class SimpleAbstractClass(metaclass=ABCMeta):
    pass
SimpleAbstractClass.register(list)
assert isinstance([], SimpleAbstractClass)
 
register() 方法呼叫接受一個類作為其引數並會讓此 ABC 成為所註冊類的子類。這一點可以透過在最後一行上呼叫 assert 語句進行驗證。清單 2 是使用修飾符的另外一個例子。
清單 2. 使用修飾符的一個抽象基類
    
from abc import ABCMeta, abstractmethod
class abstract(metaclass=ABCMeta):
    @abstractmethod
    def absMeth(self):
        pass
 
class A(abstract):
    # must implement abstract method
    def absMeth(self):
        return 0
 
瞭解了 ABC 之後,我們就可以繼續探究新的 I/O 系統了。之前的 Python 釋出版都缺少一些重要但是出色的函式,比如用於類似於流的物件的 seek()。 類似於流的物件 是一些具有 read() 和 write() 方法的類似於檔案的物件 — 比如,socket 或檔案。Python 3 具有很多針對類似於流的物件的 I/O 層 — 一個原始的 I/O 層、一個被緩衝的 I/O 層以及一個文字 I/O 層 — 每層均由其自身的 ABC 及實現定義。
開啟一個流還是需要使用內建的 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:完全緩衝(預設)
預設的編碼方式獨立於平臺。關閉檔案描述符或 closefd 可以是 True 或 False。如果是 False,此檔案描述符會在檔案關閉後保留。若檔名無法奏效的話,那麼 closefd 必須設為 True。
open() 返回的物件取決於您所設定的模式。表 1 給出了返回型別。
表 1. 針對不同開啟模式的返回型別
 模式         返回物件
文字模式    TextIOWrapper
二進位制      BufferedReader
寫二進位制    BufferedWriter
追加二進位制  BufferedWriter
讀/寫模式   BufferedRandom
請注意:文字模式可以是 w、 r、wt、 rt 等。
清單 3 中所示的例子開啟的是一個緩衝了的二進位制流以供讀取。
清單 3. 開啟一個緩衝了的二進位制流以供讀取
    
>>>import io
>>>f = io.open(“hashlib.pyo”, “rb”)  # open for reading in binary mode
>>>f                                 # f is a BufferedReader object
>>>f.close()                         # close stream
 
BufferedReader 物件可以訪問很多有用的方法,比如 isatty、 peek、raw、 readinto、readline、 readlines、seek、seekable、tell、 writable、write 和 writelines。要想檢視完整列表,可以在 BufferedReader 物件上執行 dir()。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22664653/viewspace-702985/,如需轉載,請註明出處,否則將追究法律責任。

相關文章