成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Python2 和 Python3 的區(qū)別及兼容技巧

lmxdawn / 3408人閱讀

摘要:前言最近之父龜爺終于在官方郵件組落實(shí)了的終焉之日。于之后的年月日發(fā)布,計(jì)劃作為的最后一個(gè)版本。統(tǒng)一使用作為縮進(jìn),如果和同時(shí)存在,就會(huì)觸發(fā)異常兼容技巧統(tǒng)一使用作為縮進(jìn)。兼容技巧統(tǒng)一使用內(nèi)置函數(shù)。統(tǒng)一輸出函數(shù)中的即是關(guān)鍵字又是內(nèi)置函數(shù)。

前言

最近 Python 之父 Guido van Rossum(龜爺)終于在 Python 官方郵件組落實(shí)了 Python 2.7 的終焉之日(EOL)。
說(shuō)的是 Python 2.7 的 EOL 日期最終確定為 2020 年 1 月 1 日,之后不會(huì)有任何更新,包括源碼的安全補(bǔ)丁。
所以兼容Python3已經(jīng)可以說(shuō)非常必要了,但有些常用的庫(kù)還沒(méi)有升級(jí)到Python3,所以我們看下如何寫出兼容2和3的代碼。
Python 2 or 3 ?

Python 3 被欽定為 Python 的未來(lái),于 2008 年末發(fā)布,是目前正在開發(fā)的版本。旨在解決和修正 Python 2 遺留的設(shè)計(jì)缺陷、清理代碼庫(kù)冗余、追求有且僅有一種最佳實(shí)踐方式來(lái)執(zhí)行任務(wù)等問(wèn)題。

起初,由于 Python 3 不能向后兼容的事實(shí),導(dǎo)致了用戶采用緩慢,對(duì)初學(xué)者不友好等問(wèn)題。但在 Python 社區(qū)的努力和決絕態(tài)度下,截至龜爺發(fā)出郵件之前,已經(jīng)有了 21903 個(gè) Packages 可以支持 Python 3.5,其中包括了絕大多數(shù)最受歡迎的封裝庫(kù),與此同時(shí)也有越來(lái)越多的封裝庫(kù)(e.g. Django、Numpy)表示其新版本將不再支持 Python 2。

Python 2.7 于 3.0 之后的 2010 年 7 月 3 日發(fā)布,計(jì)劃作為 2.x 的最后一個(gè)版本。Python 2.7 的歷史任務(wù)在于通過(guò)提供 2 和 3 之間的兼容性措施,使 Python 2.x 的用戶更容易將代碼移植到 Python 3.x 上。那么如果你希望自己的代碼能夠兼容兩個(gè)不同的版本,首先你起碼要讓代碼能夠正常的運(yùn)行在 Python 2.7 上。

注:下文使用 P2 表示 Python 2.7;使用 P3 表示 Python 3.x。
不同與兼容

future 模塊是我們首先需要了解的,該模塊最主要的作用是支持在 P2 中導(dǎo)入那些在 P3 才生效的模塊和函數(shù)。是一個(gè)非常優(yōu)秀的兼容性工具庫(kù),在下文中給出的許多 兼容技巧 實(shí)例都依賴于它。

特性 在此版本可選 在此版本內(nèi)置 效果
nested_scopes 2.1.0b1 2.2 PEP 227:靜態(tài)嵌套作用域
generators 2.2.0a1 2.3 PEP 255:簡(jiǎn)單生成器
division 2.2.0a2 3.0 PEP 238:除法操作符改動(dòng)
absolute_import 2.5.0a1 3.0 PEP 328:Imports 多行導(dǎo)入與絕對(duì)相對(duì)路徑
with_statement 2.5.0a1 2.6 PEP 343:with 語(yǔ)句
print_function 2.6.0a2 3.0 PEP 3105:print 語(yǔ)句升級(jí)為函數(shù)
unicode_literals 2.6.0a2 3.0 PEP 3112:Bytes 類型
(__future__ 功能列表)

統(tǒng)一不等于語(yǔ)法

P2 支持使用 <> 和 != 表示不等于。
P3 僅支持使用 != 表示不等于。
兼容技巧:

統(tǒng)一使用 != 語(yǔ)法

統(tǒng)一整數(shù)類型

P2 中整數(shù)類型可以細(xì)分為短整型 int 和長(zhǎng)整型 long。
P3 廢除了短整型,并統(tǒng)一使用 int 表示長(zhǎng)整型(不再有 L 跟在 repr 后面)。
兼容技巧:

1
2
3
4

Python 2 only

k = 9223372036854775808L

Python 2 and 3:

k = 9223372036854775808
1
2
3
4
5

Python 2 only

bigint = 1L

Python 2 and 3

from future.builtins import int
bigint = int(1)
統(tǒng)一整數(shù)除法

P2 的除法 / 符號(hào)實(shí)際上具有兩個(gè)功能:
當(dāng)兩個(gè)操作數(shù)均為整型對(duì)象時(shí),進(jìn)行的是地板除(截除小數(shù)部分),返回整型對(duì)象;
當(dāng)兩個(gè)操作數(shù)存在至少一個(gè)浮點(diǎn)型對(duì)象時(shí),進(jìn)行的是真除(保留小數(shù)部分),返回浮點(diǎn)型對(duì)象。
P3 的除法 / 符號(hào)僅僅具有真除的功能,而地板除的功能則交由 // 來(lái)完成。
兼容技巧:

1
2
3
4
5

Python 2 only:

assert 2 / 3 == 0

Python 2 and 3:

assert 2 // 3 == 0
“True division” (float division):
1
2
3
4

Python 3 only:

assert 3 / 2 == 1.5

Python 2 and 3:

from future import division # (at top of module)
統(tǒng)一縮進(jìn)語(yǔ)法

P2 可以混合使用 tab 和 space 兩種方式來(lái)進(jìn)行縮進(jìn)(1 個(gè) tab == 8 個(gè) space),但實(shí)際上這一特性并非所有 IDE 都能夠支持,會(huì)因此出現(xiàn)同樣的代碼無(wú)法跨 IDE 運(yùn)行的情況。
P3 統(tǒng)一使用 tab 作為縮進(jìn),如果 tab 和 space 同時(shí)存在,就會(huì)觸發(fā)異常:
1
TabError: inconsistent use of tabs and spaces in indentation.
兼容技巧:

統(tǒng)一使用 tab 作為縮進(jìn)。
統(tǒng)一類定義

P2 同時(shí)支持新式類(object)和老式類。
P3 則統(tǒng)一使用新式類,并且只有使用新式類才能應(yīng)用多重繼承。
兼容技巧:

統(tǒng)一使用新式類。

統(tǒng)一字符編碼類型

P2 默認(rèn)使用 ASCII 字符編碼,但因?yàn)?ASCII 只支持?jǐn)?shù)百個(gè)字符,并不能靈活的滿足非英文字符,所以 P2 同時(shí)也支持 Unicode 這種更強(qiáng)大的字符編碼。不過(guò),由于 P2 同時(shí)支持兩套字符編碼,就難免多出了一些標(biāo)識(shí)和轉(zhuǎn)換的麻煩。
而 P3 統(tǒng)一使用 Unicode 字符編碼,這節(jié)省了開發(fā)者的時(shí)間,同時(shí)也可以輕松地在程序中輸入和顯示更多種類的字符。
兼容技巧:

在所有的字符串賦值中均使用前綴 u,或引入 unicode_literals 字符模塊。
1
2
3
4
5
6
7
8
9
10

Python 2 only

s1 = "PythonTab"
s2 = u"PythonTab中文網(wǎng)"

Python 2 and 3

s1 = u"PythonTab"
s2 = u"PythonTab中文網(wǎng)"

Python 2 and 3

from future import unicode_literals # at top of module
s1 = "PythonTab"
s2 = "PythonTab中文網(wǎng)"
統(tǒng)一導(dǎo)入模塊的路徑搜索方式

P2 導(dǎo)入一個(gè)模塊時(shí)首先會(huì)搜索當(dāng)前目錄(cwd),若非,則搜索環(huán)境變量路徑(sys.path)。這一特性時(shí)常給開發(fā)者帶來(lái)困擾,相信大家都曾經(jīng)碰到過(guò),尤其當(dāng)自定義模塊與系統(tǒng)模塊重名的時(shí)候;
為了解決這個(gè)問(wèn)題,默認(rèn)的 P3 僅會(huì)搜索環(huán)境變量路徑,當(dāng)你需要搜索自定義模塊時(shí),你可以在包管理模式下將項(xiàng)目路徑加入到環(huán)境變量中,然后再使用絕對(duì)路徑和相對(duì)路徑(以 . 開頭)的方式來(lái)導(dǎo)入。
兼容技巧:

統(tǒng)一使用絕對(duì)路徑進(jìn)行自定義模塊導(dǎo)入。

修正列表推導(dǎo)式的變量作用域泄露

P2 的列表推倒式中的變量會(huì)泄露到全局作用域,例如:
1
2
3
4
5
6
7
8
9
10
11
import platform
print("Python", platform.python_version())
i = 1
print("before: I = %s" % i)
print("comprehension: %s" % [i for i in range(5)])
print("after: I = %s" % i)

OUT

Python 2.7.6
before: i = 1
comprehension: [0, 1, 2, 3, 4]
after: i = 4
P3 則解決了這個(gè)問(wèn)題,列表推倒式中的變量不再泄露到全局作用域。
1
2
3
4
5
6
7
8
9
10
11
import platform
print("Python", platform.python_version())
i = 1
print("before: i =", i)
print("comprehension:", [i for i in range(5)])
print("after: i =", i)

OUT

Python 3.4.1
before: i = 1
comprehension: [0, 1, 2, 3, 4]
after: i = 1
修正非法比較操作異常

P2 能夠?qū)蓚€(gè)數(shù)據(jù)類型并不相同的對(duì)象進(jìn)行比較。
1
2
3
4
5
import platform
print("Python", platform.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))

OUT

1
2
3
4
Python 2.7.6
[1, 2] > "foo" = False
(1, 2) > "foo" = True
[1, 2] > (1, 2) = False
不過(guò),這種看似方便的特性,實(shí)際上卻是一個(gè)定時(shí)炸彈,因?yàn)槟銦o(wú)法唯一的確定到底是什么原因?qū)е碌姆祷刂禐?False(可能是數(shù)據(jù)比較、也可能是數(shù)據(jù)類型不一致)。

P3 則對(duì)其進(jìn)行了修正,如果比較操作數(shù)類型不一致時(shí),會(huì)觸發(fā) TypeError 異常。
兼容技巧:

永遠(yuǎn)不要比較數(shù)據(jù)類型不一致的對(duì)象。

統(tǒng)一拋出異常語(yǔ)法

P2 同時(shí)支持新舊兩種異常觸發(fā)語(yǔ)法:
1
2
raise IOError, "file error" # Old
raise IOError("file error") # New
P3 則統(tǒng)一使用新異常觸發(fā)語(yǔ)法,否則會(huì)觸發(fā) SyntaxError 異常:
1
raise IOError("file error")
兼容技巧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

拋出異常 Python 2 only:

raise ValueError, "dodgy value"

Python 2 and 3:

raise ValueError("dodgy value")

使用 traceback 拋出異常 Python 2 only:

traceback = sys.exc_info()[2]
raise ValueError, "dodgy value", traceback

Python 3 only:

raise ValueError("dodgy value").with_traceback()

Python 2 and 3: option 1

from six import reraise as raise_

or # from future.utils import raise_

traceback = sys.exc_info()[2]
raise_(ValueError, "dodgy value", traceback)

Python 2 and 3: option 2

from future.utils import raise_with_traceback
raise_with_traceback(ValueError("dodgy value"))

異常鏈處理 Setup:

class DatabaseError(Exception):

pass
Python 3 only

class FileDatabase:

def __init__(self, filename):
    try:
        self.file = open(filename)
    except IOError as exc:
        raise DatabaseError("failed to open") from exc
Python 2 and 3:

from future.utils import raise_from
class FileDatabase:

def __init__(self, filename):
    try:
        self.file = open(filename)
    except IOError as exc:
        raise_from(DatabaseError("failed to open"), exc)

統(tǒng)一異常處理語(yǔ)法

P2 實(shí)現(xiàn)異常處理也能夠支持兩種語(yǔ)法。
1
2
3
4
5
try:

let_us_cause_a_NameError

except NameError, err:

except NameError as err:
print err, "--> our error message"

P3 的異常處理則強(qiáng)制要求使用 as 關(guān)鍵字的方式。
1
2
3
4
try:

let_us_cause_a_NameError

except NameError as err:

print(err, "--> our error message")

兼容技巧:

統(tǒng)一使用 as 關(guān)鍵字的異常處理方式。
統(tǒng)一輸入函數(shù)

P2 支持 raw_input 和 input 兩個(gè)輸入函數(shù),區(qū)別在于前者僅能返回 String 類型對(duì)象,后者則支持返回?cái)?shù)字和字符串兩種數(shù)據(jù)類型對(duì)象,并且當(dāng)輸入為表達(dá)式時(shí),會(huì)隱式調(diào)用 eval 函數(shù)返回其執(zhí)行結(jié)果。顯然的,使用 input 是更加靈活的寫法。
所以 P3 統(tǒng)一的使用了 input 函數(shù)進(jìn)行輸入處理。

兼容技巧:

統(tǒng)一使用 input 內(nèi)置函數(shù)。
1
2
3
4
5

Python 2 only:

input("Type something safe please: ")

Python 2 and 3

from future.builtins import input
eval(input("Type something safe please: "))
統(tǒng)一輸出函數(shù)

P2 中的 print 即是關(guān)鍵字又是內(nèi)置函數(shù)。print "Hello world!" 為一條語(yǔ)句,print("Hello world!") 則為一次函數(shù)調(diào)用。
P3 統(tǒng)一使用 print 函數(shù)進(jìn)行輸出操作,其原型如下,這一改變讓 P3 的輸出處理變得更加簡(jiǎn)潔、強(qiáng)大而優(yōu)雅,通過(guò)實(shí)參的傳遞就能替代 P2 中繁復(fù)的代碼實(shí)現(xiàn)。
1
print(*objects, sep=" ", end="n", file=sys.stdout, flush=False)
兼容技巧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

單行打印單個(gè) String Python 2 only:

print "Hello"

Python 2 only:

print "Hello"

單行打印多個(gè) String Python 2 only:

print "Hello", "Guido"

Python 2 and 3:

from future import print_function # (at top of module)
print("Hello", "Guido")

輸出重定向 Python 2 only:

print >> sys.stderr, "Hello"

Python 2 and 3:

from future import print_function
print("Hello", file=sys.stderr)

換行打印 Python 2 only:

print "Hello",

Python 2 and 3:

from future import print_function
print("Hello", end="")
統(tǒng)一文件操作函數(shù)

P2 支持使用 file 和 open 兩個(gè)函數(shù)來(lái)進(jìn)行文件操作。
P3 則統(tǒng)一使用 open 來(lái)進(jìn)行文件操作。
兼容技巧:

統(tǒng)一使用 open 函數(shù)。
1
2
3
4

Python 2 only:

f = file(pathname)

Python 2 and 3:

f = open(pathname)
統(tǒng)一列表迭代器生成函數(shù)

P2 支持使用 range 和 xrange 兩個(gè)函數(shù)來(lái)生成可迭代對(duì)象,區(qū)別在于前者返回的是一個(gè)列表類型對(duì)象,后者返回的是一個(gè)類似生成器(惰性求值)的迭代對(duì)象,支持無(wú)限迭代。所以當(dāng)你需要生成一個(gè)很大的序列時(shí),推薦使用 xrange,因?yàn)樗粫?huì)一上來(lái)就索取序列所需的所有內(nèi)存空間。如果只對(duì)序列進(jìn)行讀操作的話,xrange 方法效率顯然會(huì)更高,但是如果要修改序列的元素,或者往序列增刪元素的話,那只能通過(guò) range 方法生成一個(gè) list 對(duì)象了。

P3 則統(tǒng)一使用 range 函數(shù)來(lái)生成可迭代對(duì)象,但其實(shí) P3 的 range 更像是 P2 的 xrange。所以在 P3 中如果你想得到一個(gè)可以被修改的列表對(duì)象,你需要這么做:
1
2
list(range(1,10))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
兼容技巧:

統(tǒng)一使用 range 函數(shù)
1
2
3
4
5
6
7
8
9
10
11

Python 2 only:

for i in xrange(10**8):

...
Python 2 and 3: forward-compatible

from future.builtins import range
for i in range(10**8):

...
Python 2 and 3: backward-compatible

from past.builtins import xrange
for i in xrange(10**8):

...

統(tǒng)一迭代器迭代函數(shù)

P2 中支持使用內(nèi)置函數(shù) next 和迭代器對(duì)象的 .next() 實(shí)例方法這兩種方式來(lái)獲取迭代器對(duì)象的下一個(gè)元素。所以,在實(shí)現(xiàn)自定義迭代器對(duì)象類時(shí),必須實(shí)現(xiàn) .next() 實(shí)例方法:
1
2
3
4
5
6
7
8
9
10
11

Python 2 only

class Upper(object):

def __init__(self, iterable):
    self._iter = iter(iterable)
def next(self):          # Py2-styface iterator interface
    return self._iter.next().upper()
def __iter__(self):
    return self

itr = Upper("hello")
assert itr.next() == "H" # Py2-style
assert list(itr) == list("ELLO")
但在 P3 中統(tǒng)一了使用 next 內(nèi)置函數(shù)來(lái)獲取下一個(gè)元素,如果試圖調(diào)用 .next() 方法則會(huì)觸發(fā) AttributeError 異常。所以,在 P3 中實(shí)現(xiàn)自定義迭代器所要實(shí)現(xiàn)的是 next 特殊方法。

兼容技巧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

Python 2 and 3: option 1

from future.builtins import object
class Upper(object):

def __init__(self, iterable):
    self._iter = iter(iterable)
def __next__(self):      # Py3-style iterator interface
    return next(self._iter).upper()  # builtin next() function calls
def __iter__(self):
    return self

itr = Upper("hello")
assert next(itr) == "H" # compatible style
assert list(itr) == list("ELLO")

Python 2 and 3: option 2

from future.utils import implements_iterator
@implements_iterator
class Upper(object):

def __init__(self, iterable):
    self._iter = iter(iterable)
def __next__(self):                  # Py3-style iterator interface
    return next(self._iter).upper()  # builtin next() function calls
def __iter__(self):
    return self

itr = Upper("hello")
assert next(itr) == "H"
assert list(itr) == list("ELLO")

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/43311.html

相關(guān)文章

  • 同樣是Python,Python3Python2怎么區(qū)別這么大?

    摘要:可是當(dāng)我測(cè)試,我就懵逼了,中文真都驗(yàn)證通過(guò),不對(duì)啊,我以前也是這么過(guò)濾參數(shù)的,測(cè)試沒(méi)問(wèn)題啊唯一的區(qū)別是現(xiàn)在用的是。 上周,我的測(cè)試同事告訴我,你的用戶名怎么還允許中文???當(dāng)時(shí)我心里就想,你們測(cè)試肯定又搞錯(cuò)接口了,我用的是正則w過(guò)濾了參數(shù),怎么可能出錯(cuò),除非Python正則系統(tǒng)出錯(cuò)了,那是不可能的。本著嚴(yán)謹(jǐn)?shù)淖黠L(fēng),我自己先測(cè)試一下,沒(méi)問(wèn)題看我怎么懟回去。可是當(dāng)我測(cè)試,我就懵逼了,中文真T...

    Raaabbit 評(píng)論0 收藏0
  • 詳解python2python3區(qū)別

    摘要:認(rèn)為有極大的優(yōu)化空間,在字符串和整形操作上可以取得很好的優(yōu)化結(jié)果。的和方法返回迭代器,而之前的等函數(shù)都被廢棄。python有兩個(gè)主要的版本,python2 和 python3 ,但是python又不同于其他語(yǔ)言,向下兼容,python3是不向下兼容的,但是絕大多數(shù)組件和擴(kuò)展都是基于python2的,下面就來(lái)總結(jié)一下python2和python3的區(qū)別。 ? 1.性能? Py3.0運(yùn)...

    Sourcelink 評(píng)論0 收藏0
  • 詳解python2python3區(qū)別

    摘要:認(rèn)為有極大的優(yōu)化空間,在字符串和整形操作上可以取得很好的優(yōu)化結(jié)果。的和方法返回迭代器,而之前的等函數(shù)都被廢棄。python有兩個(gè)主要的版本,python2 和 python3 ,但是python又不同于其他語(yǔ)言,向下兼容,python3是不向下兼容的,但是絕大多數(shù)組件和擴(kuò)展都是基于python2的,下面就來(lái)總結(jié)一下python2和python3的區(qū)別。 ? 1.性能? Py3.0運(yùn)...

    Martin91 評(píng)論0 收藏0
  • Python入門-Python簡(jiǎn)介

    摘要:年月宣布支持時(shí)間延長(zhǎng)到年。更詳細(xì)的發(fā)布列表參閱官網(wǎng)的版本號(hào)分為三段,形如。其中表示大版本號(hào),一般當(dāng)整體重寫,或出現(xiàn)不向后兼容的改變時(shí),增加表示功能更新,出現(xiàn)新功能時(shí)增加表示小的改動(dòng)如修復(fù)了某個(gè),只要有修改就增加。年公司正式發(fā)布。 < 返回索引頁(yè) Python語(yǔ)言簡(jiǎn)介 Python介紹及發(fā)展 介紹 Python 官方網(wǎng)站:https://www.python.org/, 大家可以到此處下...

    Java_oldboy 評(píng)論0 收藏0
  • 同樣是Python,怎么區(qū)別這么大

    摘要:可是當(dāng)我測(cè)試,我就懵逼了,中文真都驗(yàn)證通過(guò),不對(duì)啊,我以前也是這么過(guò)濾參數(shù)的,測(cè)試沒(méi)問(wèn)題啊唯一的區(qū)別是現(xiàn)在用的是。 發(fā)現(xiàn)問(wèn)題 上周,我的測(cè)試同事告訴我,你的用戶名怎么還允許中文???當(dāng)時(shí)我心里就想,你們測(cè)試肯定又搞錯(cuò)接口了,我用的是正則w過(guò)濾了參數(shù),怎么可能出錯(cuò),除非Python正則系統(tǒng)出錯(cuò)了,那是不可能的。本著嚴(yán)謹(jǐn)?shù)淖黠L(fēng),我自己先測(cè)試一下,沒(méi)問(wèn)題看我怎么懟回去??墒钱?dāng)我測(cè)試,我就懵逼了...

    lovXin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<