摘要:跳轉(zhuǎn)到章節(jié)預(yù)覽在中創(chuàng)建迭代對(duì)象的用法是非常流行的。循環(huán)變量和全局命名空間泄漏好消息在中循環(huán)變量不會(huì)再導(dǎo)致命名空間泄漏。通過解析用戶的輸入幸運(yùn)的是,在中已經(jīng)解決了把用戶的輸入存儲(chǔ)為一個(gè)對(duì)象的問題。
注:本文的原文地址為
Key differences between Python 2.7.x and Python 3.x
許多 Python 初學(xué)者想知道他們應(yīng)該從 Python 的哪個(gè)版本開始學(xué)習(xí)。對(duì)于這個(gè)問題我的答案是 “你學(xué)習(xí)你喜歡的教程的版本,然后檢查他們之間的不同。"
但是如果你開始一個(gè)新項(xiàng)目,并且有選擇權(quán)?我想說的是目前沒有對(duì)錯(cuò),只要你計(jì)劃使用的庫 Python 2.7.x 和 Python 3.x 雙方都支持的話。盡管如此,當(dāng)在編寫它們中的任何一個(gè)的代碼,或者是你計(jì)劃移植你的項(xiàng)目的時(shí)候,是非常值得看看這兩個(gè)主要流行的 Python 版本之間的差別的,以便避免常見的陷阱,
章節(jié)使用 __future__ 模塊
print 函數(shù)
Integer division
Unicode
xrange
Raising exceptions
Handling exceptions
next() 函數(shù) 和 .next() 方法
For 循環(huán)變量和全局命名空間泄漏
比較不可排序類型
通過 input() 解析用戶的輸入
返回可迭代對(duì)象,而不是列表
更多的關(guān)于 Python 2 和 Python 3 的文章
future 模塊Python 3.x 介紹的 一些Python 2 不兼容的關(guān)鍵字和特性可以通過在 Python 2 的內(nèi)置 __future__ 模塊導(dǎo)入。如果你計(jì)劃讓你的代碼支持 Python 3.x,建議你使用 __future__ 模塊導(dǎo)入。例如,如果我想要 在Python 2 中表現(xiàn) Python 3.x 中的整除,我們可以通過如下導(dǎo)入
from __future__ import division
更多的 __future__ 模塊可被導(dǎo)入的特性被列在下表中:
feature | optional in | mandatory in | effect |
---|---|---|---|
nested_scopes | 2.1.0b1 | 2.2 | PEP 227: Statically Nested Scopes |
generators | 2.2.0a1 | 2.3 | PEP 255: Simple Generators |
division | 2.2.0a2 | 3.0 | PEP 238: Changing the Division Operator |
absolute_import | 2.5.0a1 | 3.0 | PEP 328: Imports: Multi-Line and Absolute/Relative |
with_statement | 2.5.0a1 | 2.6 | PEP 343: The “with” Statement |
print_function | 2.6.0a2 | 3.0 | PEP 3105: Make print a function |
unicode_literals | 2.6.0a2 | 3.0 | PEP 3112: Bytes literals in Python 3000 |
(Source: https://docs.python.org/2/library/future.html)
from platform import python_versionprint 函數(shù)
[跳轉(zhuǎn)到章節(jié)預(yù)覽]
很瑣碎,而 print 語法的變化可能是最廣為人知的了,但是仍值得一提的是: Python 2 的 print 聲明已經(jīng)被 print() 函數(shù)取代了,這意味著我們必須包裝我們想打印在小括號(hào)中的對(duì)象。
Python 2 不具有額外的小括號(hào)問題。但對(duì)比一下,如果我們按照 Python 2 的方式不使用小括號(hào)調(diào)用 print 函數(shù),Python 3 將拋出一個(gè)語法異常(SyntaxError)。
Python 2
print "Python", python_version() print "Hello, World!" print("Hello, World!") print "text", ; print "print more text on the same line"
Python 2.7.6 Hello, World! Hello, World! text print more text on the same line
Python 3
print("Python", python_version()) print("Hello, World!") print("some text,", end="") print(" print more text on the same line")
Python 3.4.1 Hello, World! some text, print more text on the same line
print "Hello, World!"
File "", line 1 print "Hello, World!" ^ SyntaxError: invalid syntax
注意
以上通過 Python 2 使用 Printing "Hello, World" 是非常正常的,盡管如此,如果你有多個(gè)對(duì)象在小括號(hào)中,我們將創(chuàng)建一個(gè)元組,因?yàn)?print 在 Python 2 中是一個(gè)聲明,而不是一個(gè)函數(shù)調(diào)用。
print "Python", python_version() print("a", "b") print "a", "b"
Python 2.7.7 ("a", "b") a b整除
[跳轉(zhuǎn)到章節(jié)預(yù)覽]
如果你正在移植代碼,這個(gè)變化是特別危險(xiǎn)的?;蛘吣阍?Python 2 上執(zhí)行 Python 3 的代碼。因?yàn)檫@個(gè)整除的變化表現(xiàn)在它會(huì)被忽視(即它不會(huì)拋出語法異常)。
因此,我還是傾向于使用一個(gè) float(3)/2 或 3/2.0 代替在我的 Python 3 腳本保存在 Python 2 中的 3/2 的一些麻煩(并且反而過來也一樣,我建議在你的 Python 2 腳本中使用 from __future__ import division)
Python 2
print "Python", python_version() print "3 / 2 =", 3 / 2 print "3 // 2 =", 3 // 2 print "3 / 2.0 =", 3 / 2.0 print "3 // 2.0 =", 3 // 2.0
Python 2.7.6 3 / 2 = 1 3 // 2 = 1 3 / 2.0 = 1.5 3 // 2.0 = 1.0
Python 3
print("Python", python_version()) print("3 / 2 =", 3 / 2) print("3 // 2 =", 3 // 2) print("3 / 2.0 =", 3 / 2.0) print("3 // 2.0 =", 3 // 2.0)
Unicode
Python 3.4.1 3 / 2 = 1.5 3 // 2 = 1 3 / 2.0 = 1.5 3 // 2.0 = 1.0
[跳轉(zhuǎn)到章節(jié)預(yù)覽]
Python 2 有 ASCII str() 類型,unicode() 是多帶帶的,不是 byte 類型。
現(xiàn)在, 在 Python 3,我們最終有了 Unicode (utf-8) 字符串,以及一個(gè)字節(jié)類:byte 和 bytearrays。
Python 2
print "Python", python_version()
Python 2.7.6
print type(unicode("this is like a python3 str type"))
print type(b"byte type does not exist")
print "they are really" + b" the same" they are really the same
print type(bytearray(b"bytearray oddly does exist though"))
Python 3
print("Python", python_version()) print("strings are now utf-8 u03BCnicou0394é!") Python 3.4.1 strings are now utf-8 μnicoΔé!
print("Python", python_version(), end="") print(" has", type(b" bytes for storing data")) Python 3.4.1 has
print("and Python", python_version(), end="") print(" also has", type(bytearray(b"bytearrays"))) and Python 3.4.1 also has
"note that we cannot add a string" + b"bytes for data" --------------------------------------------------------------------------- TypeError Traceback (most recent call last)xrangein () ----> 1 "note that we cannot add a string" + b"bytes for data" TypeError: Can"t convert "bytes" object to str implicitly
[跳轉(zhuǎn)到章節(jié)預(yù)覽]
在 Python 2 中 xrange() 創(chuàng)建迭代對(duì)象的用法是非常流行的。比如: for 循環(huán)或者是列表/集合/字典推導(dǎo)式。
這個(gè)表現(xiàn)十分像生成器(比如?!岸栊郧笾怠保5沁@個(gè) xrange-iterable 是無窮的,意味著你可以無限遍歷。
由于它的惰性求值,如果你不得僅僅不遍歷它一次,xrange() 函數(shù) 比 range() 更快(比如 for 循環(huán))。盡管如此,對(duì)比迭代一次,不建議你重復(fù)迭代多次,因?yàn)樯善髅看味紡念^開始。
在 Python 3 中,range() 是像 xrange() 那樣實(shí)現(xiàn)以至于一個(gè)專門的 xrange() 函數(shù)都不再存在(在 Python 3 中 xrange() 會(huì)拋出命名異常)。
import timeit n = 10000 def test_range(n): return for i in range(n): pass def test_xrange(n): for i in xrange(n): pass
Python 2
print "Python", python_version() print " timing range()" %timeit test_range(n) print " timing xrange()" %timeit test_xrange(n) Python 2.7.6 timing range() 1000 loops, best of 3: 433 μs per loop timing xrange() 1000 loops, best of 3: 350 μs per loop
Python 3
print("Python", python_version()) print(" timing range()") %timeit test_range(n) Python 3.4.1 timing range() 1000 loops, best of 3: 520 μs per loop
print(xrange(10)) --------------------------------------------------------------------------- NameError Traceback (most recent call last)in () ----> 1 print(xrange(10)) NameError: name "xrange" is not defined
Python 3 中的 range 對(duì)象的 __contains__ 方法
另外一件值得一提的事情就是在 Python 3 中 range 有一個(gè)新的 __contains__ 方法(感謝 Yuchen Ying 指出了這個(gè)),__contains__ 方法可以加速 "查找" 在 Python 3.x 中顯著的整數(shù)和布爾類型。
x = 10000000 def val_in_range(x, val): return val in range(x) def val_in_xrange(x, val): return val in xrange(x) print("Python", python_version()) assert(val_in_range(x, x/2) == True) assert(val_in_range(x, x//2) == True) %timeit val_in_range(x, x/2) %timeit val_in_range(x, x//2) Python 3.4.1 1 loops, best of 3: 742 ms per loop 1000000 loops, best of 3: 1.19 μs per loop
基于以上的 timeit 的結(jié)果,當(dāng)它使一個(gè)整數(shù)類型,而不是浮點(diǎn)類型的時(shí)候,你可以看到執(zhí)行查找的速度是 60000 倍快。盡管如此,因?yàn)?Python 2.x 的 range 或者是 xrange 沒有一個(gè) __contains__ 方法,這個(gè)整數(shù)類型或者是浮點(diǎn)類型的查詢速度不會(huì)相差太大。
print "Python", python_version() assert(val_in_xrange(x, x/2.0) == True) assert(val_in_xrange(x, x/2) == True) assert(val_in_range(x, x/2) == True) assert(val_in_range(x, x//2) == True) %timeit val_in_xrange(x, x/2.0) %timeit val_in_xrange(x, x/2) %timeit val_in_range(x, x/2.0) %timeit val_in_range(x, x/2) Python 2.7.7 1 loops, best of 3: 285 ms per loop 1 loops, best of 3: 179 ms per loop 1 loops, best of 3: 658 ms per loop 1 loops, best of 3: 556 ms per loop
下面說下 __contain__ 方法并沒有加入到 Python 2.x 中的證據(jù):
print("Python", python_version()) range.__contains__ Python 3.4.1
print "Python", python_version() range.__contains__ Python 2.7.7 --------------------------------------------------------------------------- AttributeError Traceback (most recent call last)in () 1 print "Python", python_version() ----> 2 range.__contains__ AttributeError: "builtin_function_or_method" object has no attribute "__contains__"
print "Python", python_version() xrange.__contains__ Python 2.7.7 --------------------------------------------------------------------------- AttributeError Traceback (most recent call last)in () 1 print "Python", python_version() ----> 2 xrange.__contains__ AttributeError: type object "xrange" has no attribute "__contains__"
**注意在 Python 2 和 Python 3 中速度的不同***
有些猿類指出了 Python 3 的 range() 和 Python 2 的 xrange() 之間的速度不同。因?yàn)樗麄兪怯孟嗤姆椒▽?shí)現(xiàn)的,因此期望相同的速度。盡管如此,這事實(shí)在于 Python 3 傾向于比 Python 2 運(yùn)行的慢一點(diǎn)。
def test_while(): i = 0 while i < 20000: i += 1 return
print("Python", python_version()) %timeit test_while() Python 3.4.1 100 loops, best of 3: 2.68 ms per loop
print "Python", python_version() %timeit test_while() Python 2.7.6 1000 loops, best of 3: 1.72 ms per loopRaising exceptions
[跳轉(zhuǎn)到章節(jié)預(yù)覽]
Python 2 接受新舊兩種語法標(biāo)記,在 Python 3 中如果我不用小括號(hào)把異常參數(shù)括起來就會(huì)阻塞(并且反過來引發(fā)一個(gè)語法異常)。
Python 2
print "Python", python_version() Python 2.7.6
raise IOError, "file error" --------------------------------------------------------------------------- IOError Traceback (most recent call last)in () ----> 1 raise IOError, "file error" IOError: file error
raise IOError("file error") --------------------------------------------------------------------------- IOError Traceback (most recent call last)in () ----> 1 raise IOError("file error") IOError: file error
Python 3
print("Python", python_version()) Python 3.4.1
raise IOError, "file error"
File "", line 1 raise IOError, "file error" ^ SyntaxError: invalid syntax The proper way to raise an exception in Python 3:
Handling exceptions
print("Python", python_version()) raise IOError("file error") Python 3.4.1 --------------------------------------------------------------------------- OSError Traceback (most recent call last)in () 1 print("Python", python_version()) ----> 2 raise IOError("file error") OSError: file error
在 Python 3 中處理異常也輕微的改變了,在 Python 3 中我們現(xiàn)在使用 as 作為關(guān)鍵詞。
python 2
print "Python", python_version() try: let_us_cause_a_NameError except NameError, err: print err, "--> our error message" Python 2.7.6 name "let_us_cause_a_NameError" is not defined --> our error message
Python 3
print("Python", python_version()) try: let_us_cause_a_NameError except NameError as err: print(err, "--> our error message") Python 3.4.1 name "let_us_cause_a_NameError" is not defined --> our error messagenext() 函數(shù) and .next() 方法
因?yàn)?next() (.next()) 是一個(gè)如此普通的使用函數(shù)(方法),這里有另外一個(gè)語法改變(或者是實(shí)現(xiàn)上改變了),值得一提的是:在 Python 2.7.5 中函數(shù)和方法你都可以使用,next() 函數(shù)在 Python 3 中一直保留著(調(diào)用 .next() 拋出屬性異常)。
Python 2
print "Python", python_version() my_generator = (letter for letter in "abcdefg") next(my_generator) my_generator.next()
Python 2.7.6 "b"
Python 3
print("Python", python_version()) my_generator = (letter for letter in "abcdefg") next(my_generator)
Python 3.4.1 "a"
my_generator.next()
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last)For 循環(huán)變量和全局命名空間泄漏in () ----> 1 my_generator.next() AttributeError: "generator" object has no attribute "next"
好消息:在 Python 3.x 中 for 循環(huán)變量不會(huì)再導(dǎo)致命名空間泄漏。
在 Python 3.x 中做了一個(gè)改變,在 What’s New In Python 3.0 中有如下描述:
"列表推導(dǎo)不再支持 [... for var in item1, item2, ...] 這樣的語法。使用 [... for var in (item1, item2, ...)] 代替。也需要提醒的是列表推導(dǎo)有不同的語義: 他們關(guān)閉了在 `list()` 構(gòu)造器中的生成器表達(dá)式的語法糖, 并且特別是循環(huán)控制變量不再泄漏進(jìn)周圍的作用范圍域."
Python 2
print "Python", python_version() i = 1 print "before: i =", i print "comprehension: ", [i for i in range(5)] print "after: i =", i Python 2.7.6 before: i = 1 comprehension: [0, 1, 2, 3, 4] after: i = 4
Python 3
print("Python", python_version()) i = 1 print("before: i =", i) print("comprehension:", [i for i in range(5)]) print("after: i =", i) Python 3.4.1 before: i = 1 comprehension: [0, 1, 2, 3, 4] after: i = 1比較不可排序類型
在 Python 3 中的另外一個(gè)變化就是當(dāng)對(duì)不可排序類型做比較的時(shí)候,會(huì)拋出一個(gè)類型錯(cuò)誤。
Python 2
print "Python", python_version() print "[1, 2] > "foo" = ", [1, 2] > "foo" print "(1, 2) > "foo" = ", (1, 2) > "foo" print "[1, 2] > (1, 2) = ", [1, 2] > (1, 2) Python 2.7.6 [1, 2] > "foo" = False (1, 2) > "foo" = True [1, 2] > (1, 2) = False
Python 3
print("Python", python_version()) print("[1, 2] > "foo" = ", [1, 2] > "foo") print("(1, 2) > "foo" = ", (1, 2) > "foo") print("[1, 2] > (1, 2) = ", [1, 2] > (1, 2)) Python 3.4.1 --------------------------------------------------------------------------- TypeError Traceback (most recent call last)通過 input() 解析用戶的輸入in () 1 print("Python", python_version()) ----> 2 print("[1, 2] > "foo" = ", [1, 2] > "foo") 3 print("(1, 2) > "foo" = ", (1, 2) > "foo") 4 print("[1, 2] > (1, 2) = ", [1, 2] > (1, 2)) TypeError: unorderable types: list() > str()
幸運(yùn)的是,在 Python 3 中已經(jīng)解決了把用戶的輸入存儲(chǔ)為一個(gè) str 對(duì)象的問題。為了避免在 Python 2 中的讀取非字符串類型的危險(xiǎn)行為,我們不得不使用 raw_input() 代替。
Python 2
Python 2.7.6 [GCC 4.0.1 (Apple Inc. build 5493)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> my_input = input("enter a number: ") enter a number: 123 >>> type(my_input)>>> my_input = raw_input("enter a number: ") enter a number: 123 >>> type(my_input)
Python 3
Python 3.4.1 [GCC 4.2.1 (Apple Inc. build 5577)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> my_input = input("enter a number: ") enter a number: 123 >>> type(my_input)返回可迭代對(duì)象,而不是列表
如果在 xrange 章節(jié)看到的,現(xiàn)在在 Python 3 中一些方法和函數(shù)返回迭代對(duì)象 -- 代替 Python 2 中的列表
因?yàn)槲覀兺ǔD切┍闅v只有一次,我認(rèn)為這個(gè)改變對(duì)節(jié)約內(nèi)存很有意義。盡管如此,它也是可能的,相對(duì)于生成器 --- 如需要遍歷多次。它是不那么高效的。
而對(duì)于那些情況下,我們真正需要的是列表對(duì)象,我們可以通過 list() 函數(shù)簡(jiǎn)單的把迭代對(duì)象轉(zhuǎn)換成一個(gè)列表。
Python 2
print "Python", python_version() print range(3) print type(range(3)) Python 2.7.6 [0, 1, 2]
Python 3
print("Python", python_version()) print(range(3)) print(type(range(3))) print(list(range(3))) Python 3.4.1 range(0, 3)[0, 1, 2]
在 Python 3 中一些經(jīng)常使用到的不再返回列表的函數(shù)和方法:
zip()
map()
filter()
dictionary"s .keys() method
dictionary"s .values() method
dictionary"s .items() method
更多的關(guān)于 Python 2 和 Python 3 的文章下面是我建議后續(xù)的關(guān)于 Python 2 和 Python 3 的一些好文章。
移植到 Python 3
Should I use Python 2 or Python 3 for my development activity?
What’s New In Python 3.0
Porting to Python 3
Porting Python 2 Code to Python 3
How keep Python 3 moving forward
Python 3 的擁護(hù)者和反對(duì)者
10 awesome features of Python that you can"t use because you refuse to upgrade to Python 3
Everything you did not want to know about Unicode in Python 3
Python 3 is killing Python
Python 3 can revive Python
Python 3 is fine
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/37325.html
摘要:你使用的系統(tǒng)自帶的包管理器包索引也被稱為各種源碼托管服務(wù),如,,等。通過系統(tǒng)自帶的包管理器安裝使用系統(tǒng)自帶的包管理器安裝,只需要在命令行輸入相應(yīng)命令,或是使用你用來安裝其他應(yīng)用的應(yīng)用即可。 譯者按:原文寫于2011年末,雖然文中關(guān)于Python 3的一些說法可以說已經(jīng)不成立了,但是作為一篇面向從其他語言轉(zhuǎn)型到Python的程序員來說,本文對(duì)Python的生態(tài)系統(tǒng)還是做了較為全面的介紹...
摘要:與的區(qū)別默認(rèn)編碼方式是碼。中輸入內(nèi)容分為和兩個(gè)函數(shù),前者只接受文本輸入,而在中只有且統(tǒng)一將用戶的輸入存儲(chǔ)為對(duì)象。中不再使用和后綴說明長(zhǎng)整型。 python2與python3的區(qū)別python2默認(rèn)編碼方式是ascii碼。(可在文件的首行:# -*- encoding:utf-8 -*...
摘要:官方也宣布在停止對(duì)的維護(hù)。并且在很多面試過程中,面試官都會(huì)問與的區(qū)別。的版本,常被稱為,或簡(jiǎn)稱。與部分地支持這種形式的語法。捕獲異常的語法由改為。在中,表示八進(jìn)制字面量的方式只有一種,就是。已經(jīng)支援新的模組。 前言 如果你是剛接觸 Python 的初學(xué)者,那你可能是直接學(xué)習(xí) Python 3.x 版本。對(duì)于 Python 2.x 的版本是不會(huì)有所接觸。官方也宣布在 2020 停止對(duì) P...
摘要:用于下載網(wǎng)頁內(nèi)容,并將網(wǎng)頁內(nèi)容返回給。中間件位于引擎和下載器之間的鉤子框架,主要是處理引擎與下載器之間的請(qǐng)求及響應(yīng)。包含了在啟動(dòng)時(shí)進(jìn)行爬取的列表。對(duì)象經(jīng)過調(diào)度,執(zhí)行生成對(duì)象并送回給方法一般返回實(shí)例。 Scrapy 是什么 Scrapy 是一個(gè)為了爬取網(wǎng)站數(shù)據(jù),提取結(jié)構(gòu)性數(shù)據(jù)而編寫的應(yīng)用框架。 可以應(yīng)用在包括數(shù)據(jù)挖掘,信息處理或存儲(chǔ)歷史數(shù)據(jù)等一系列的程序中。其最初是為了頁面抓取 (更確切...
摘要:認(rèn)為有極大的優(yōu)化空間,在字符串和整形操作上可以取得很好的優(yōu)化結(jié)果。的和方法返回迭代器,而之前的等函數(shù)都被廢棄。python有兩個(gè)主要的版本,python2 和 python3 ,但是python又不同于其他語言,向下兼容,python3是不向下兼容的,但是絕大多數(shù)組件和擴(kuò)展都是基于python2的,下面就來總結(jié)一下python2和python3的區(qū)別。 ? 1.性能? Py3.0運(yùn)...
閱讀 4063·2023-04-26 02:13
閱讀 2280·2021-11-08 13:13
閱讀 2775·2021-10-11 10:59
閱讀 1769·2021-09-03 00:23
閱讀 1335·2019-08-30 15:53
閱讀 2326·2019-08-28 18:22
閱讀 3080·2019-08-26 10:45
閱讀 765·2019-08-23 17:58