python的3.2的一些注意事項

來源:互聯網
上載者:User

Python 版本 3,也被稱為 Python 3000Py3K(仿效 Microsoft Windows 2000 作業系統而命名的暱稱)是 Guido van Rossum 通用程式設計語言的最新版本。雖然新版本對該核心語言做了很多改進,但還是打破了與 2.x 版本的向後相容性。其他一些變化則是人們期待已久的,比如:

  • 真正的除法 — 例如,1/2 返回的是 .5
  • longint 類型被統一為一種類型,刪除了尾碼 L
  • TrueFalseNone 現在都是關鍵字。

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

如今,您將需要讓手指習慣於鍵入 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')>>>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 轉變為 strbytes 對象必須要進行解碼(稍後會詳細介紹)。位元據用 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} 通過位置參數 eggsbaconsausage 被傳遞給 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())<built-in method items of dict object at 0xb7c2468c>

注意:在 Python 內, 是惟一元素的無序集合。

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

>>>1 in d # test for membershipTrue

如下是在 dict_values 對象的條目上進行迭代的例子:

>>>for values in d.items():...     print(values) ...deadparrot

不過,如果您的確想要得到值的列表,可以對所返回的 dict 對象進行強制類型轉換。比如:

>>>keys = list(d.keys())>>>print(keys)[1,2]

回頁首

新的 I/O

元類

Wikipedia 對元類的定義是這樣的,“一個元類 是這樣一個類,其執行個體也是類。” 在本系列的第 2 部分我會對這個概念進行詳細的介紹。

在深入研究 I/O 的新機制之前,很有必要先來看看抽象基類( abstract base classes,ABC)。更深入的介紹將會在本系列的第 2 部分提供。

ABC 是一些無法被執行個體化的類。要使用 ABC,子類必須繼承自此 ABC 並且還要覆蓋其抽象方法。如果方法的首碼使用 @abstractmethod 修飾符(decorator),那麼此方法就是一個抽象方法。新的 ABC 架構還提供了 @abstractproperty 修飾符以便定義抽象屬性。可以通過匯入標準庫模組 abc 來訪問這個新架構。清單 1 所示的是一個簡單的例子。

清單 1. 一個簡單的抽象基類

from abc import ABCMetaclass SimpleAbstractClass(metaclass=ABCMeta):    passSimpleAbstractClass.register(list)assert isinstance([], SimpleAbstractClass)

register() 方法調用接受一個類作為其參數並會讓此 ABC 成為所註冊類的子類。這一點可以通過在最後一行上調用 assert 語句進行驗證。清單 2 是使用修飾符的另外一個例子。

清單 2. 使用修飾符的一個抽象基類

from abc import ABCMeta, abstractmethodclass 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

請注意:文字模式可以是 wrwtrt 等。

清單 3 中所示的例子開啟的是一個緩衝了的二進位流以供讀取。

清單 3. 開啟一個緩衝了的二進位流以供讀取

>>>import io>>>f = io.open("hashlib.pyo", "rb")  # open for reading in binary mode>>>f                                 # f is a BufferedReader object <io.BufferedReader object at 0xb7c2534c>>>>f.close()                         # close stream

BufferedReader 對象可以訪問很多有用的方法,比如 isattypeekrawreadintoreadlinereadlinesseekseekabletellwritablewritewritelines。要想查看完整列表,可以在 BufferedReader 對象上運行 dir()

 

結束語

Python 社區是否會接??版本 3 還尚在人們的猜測之中。打破向後相容性意味著將要為兩種版本提供支援。一些項目開發人員可能不太想遷移其項目,即便是使用版本 2 到 3 的轉化器。就我個人而言,我發現從 Python 版本 2 遷移到 3 其實不過是對幾個事情的重新認識:它當然不會像從 Python 遷移到 Java 或 Perl 語言那樣變化強烈。很多變化是早就在人們意料中的,比如對 dict 的實質更改。執行 print() 遠比執行 Java 的 System.out.println() 容易得多,學習起來也相對容易,所以的確能帶來一些好處。

我猜想,blogosphere 內的一些文章會讓 Python 的支援者也會誤認為其中的某些變更 — 例如對向後相容性的打破 — 具有破壞性的影響。 Lambda 本來就是準備好要刪除的,只不過一直沒有這麼做,仍保留了其原始的格式。有關保留項目的完整列表,請訪問 Python 核心開發站。如果您具備足夠的探索精神願意深入研究所有的 PEP,那麼您一定能夠從中獲得更深入的資訊。

本系列的下一期文章將會涵蓋更進階的主題,比如元類文法、ABC、修飾符、integer literal 支援、基底類型和異常。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.