欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

編寫(xiě)同時(shí)兼容Python2.x與Python3.x版本的代碼的幾個(gè)示例

 更新時(shí)間:2015年03月30日 16:11:32   作者:Wesley Chun  
這篇文章主要介紹了編寫(xiě)同時(shí)兼容Python2.x與Python3.x版本的代碼的幾個(gè)示例,在Python2.7.x的更新中由于采用了某些Python3中的代碼編寫(xiě)特性、使得在有些原本不同之處編寫(xiě)兼容性代碼成為可能,需要的朋友可以參考下

編寫(xiě)兼容Python2.x與3.x代碼

當(dāng)我們正處于Python 2.x到Python 3.x的過(guò)渡期時(shí),你可能想過(guò)是否可以在不修改任何代碼的前提下能同時(shí)運(yùn)行在Python 2和3中。這看起來(lái)還真是一個(gè)合理的訴求,但如何開(kāi)始呢?哪些Python 2 代碼在 3.x 解釋器執(zhí)行時(shí)容易出狀況呢?
print vs print()

如果你想的和我一樣,你或許會(huì)說(shuō)print語(yǔ)句,這是個(gè)很好的著手點(diǎn),先簡(jiǎn)單展示一下,print在2.x中是一條語(yǔ)句,而在3.x中它是一個(gè)關(guān)鍵字或者是保留字。換句話說(shuō),因?yàn)檫@個(gè)變化涉及到語(yǔ)言的語(yǔ)法,你不可以使用在if語(yǔ)句中,Python仍然沒(méi)有#ifdef 宏。下面嘗試把括號(hào)里面的參數(shù)打印出來(lái):

>>> print('Hello World!')
Hello World!

很酷,這個(gè)在Python2和Python3中都可以運(yùn)行,而且運(yùn)行的效果是一樣的,再來(lái)看看下面這段:
 

>>> print(10, 20) # Python 2
(10, 20)

此時(shí),你并沒(méi)有像前面那樣幸運(yùn)得到一樣的結(jié)果,Python2中打印的是元組(tuple),而在Python3中傳遞多個(gè)參數(shù)到print()里面時(shí)打印的是兩個(gè)值:
 

>>> print(10, 20) # Python 3
10 20

如果你思考得比較多的話,我們可以檢查print是否是一個(gè)關(guān)鍵字,keyword模塊包含一個(gè)關(guān)鍵字列表。print在3.x中不是關(guān)鍵字,可以簡(jiǎn)單驗(yàn)證一下:
 

>>> import keyword
>>> 'print' in keyword.kwlist
False

作為一名聰明的程序員,你可能在2.x中嘗試的時(shí)候期待的結(jié)果是True,盡管這并沒(méi)有錯(cuò),但是為了達(dá)到Python3的效果,但你仍然會(huì)因?yàn)槠渌驅(qū)е率 ?br />  

>>> import keyword
>>> if 'print' in keyword.kwlist:
...  from __future__ import print_function
...
File "", line 2
SyntaxError: from __future__ imports must occur at the beginning of the file

一種解決方案是使用一個(gè)函數(shù),其功能類似于print,其中之一是sys.stdout.write(),另一個(gè)是distutils.log.warn()。不管出于什么原因,我們決定使用后者。“hello world”的例子看起來(lái)是這樣的:
 

# Python 2.x
print 'Hello World!'
# Python 3.x
print('Hello World!')

下面的代碼就可以在兩個(gè)版本中通用:
 

# Python 2.x & 3.x compatible
from distutils.log import warn as printf
printf('Hello World!')

為什么我們不用sys.stdout.write()呢,因?yàn)槲覀冃枰砑右粋€(gè)NEWLINE字符在字符串的結(jié)尾來(lái)兼容這種行為(python2.x中write方法不會(huì)換行):
 

# Python 2.x & 3.x compatible
import sys
sys.stdout.write('Hello World!n')

Import your way to a solution

一般情況情況下,import時(shí)沒(méi)什么煩惱,只要正確的導(dǎo)入就行,但在下面代碼中,我們想導(dǎo)入urlopen()函數(shù),在Python2中,他同時(shí)存在與urllib2和urllib2中(我們使用后者),在Python3中,他被集成到了urllib.request中,而你的方案是要既能在2.x和3.x中正常工作:

try:
 from urllib2 import urlopen
except ImportError:
 from urllib.request import urlopen

出于對(duì)內(nèi)存的保護(hù),也許你對(duì)iterator(Python3)版本的zip()更加有興趣,在Python2中,iterator版本是itertools.izip()。這個(gè)函數(shù)在Python3中被重命名替換成了zip()。如果你使用迭代版本,導(dǎo)入語(yǔ)句也非常直白:
 

try:
 from itertools import izip as zip
except ImportError:
 pass

另一個(gè)列子是看來(lái)來(lái)并不怎么優(yōu)雅的StringIO類,在Python2中,純Python版本是StringIO模塊,意味著訪問(wèn)的時(shí)候是通過(guò)StringIO.StringIO,同樣還有一個(gè)更為快速的C語(yǔ)言版本,位于cStringIO.StringIO,不過(guò)這取決你的Python安裝版本,你可以優(yōu)先使用cStringIO然后是StringIO(如果cStringIO不能用的話)。在Python3中,Unicode是默認(rèn)的string類型,但是如果你做任何和網(wǎng)絡(luò)相關(guān)的操作,很有可能你不得不用ASCII/字節(jié)字符串來(lái)操作,所以代替StringIO,你要io.BytesIO,為了達(dá)到你想要的,這個(gè)導(dǎo)入看起來(lái)有點(diǎn)丑:
 

try:
 from io import BytesIO as StringIO
except ImportError:
 try:
  from cStringIO import StringIO
 except ImportError:
  from StringIO import StringIO

Putting it all together

如果你運(yùn)氣好的話,上面那些就是你要準(zhǔn)備做的全部,剩下的代碼都比開(kāi)始設(shè)置的地方更簡(jiǎn)單。如果你按照上面的方式導(dǎo)入了distutils.log.warn()[printf()],url*urlopen(),*.StringIO和一個(gè)標(biāo)準(zhǔn)的導(dǎo)入:xml.etree.ElementTree(2.5及更新的),現(xiàn)在你就可以寫(xiě)一個(gè)非常簡(jiǎn)短短的解析器來(lái)展示從Google News服務(wù)中提供的頭條故事(譯注:當(dāng)然首先得備一個(gè)梯子),只需八行代碼:
 

g = urlopen('http://news.google.com/news?topic=h&output=rss')
f = StringIO(g.read())
g.close()
tree = xml.etree.ElementTree.parse(f)
f.close()
for elmt in tree.getiterator():
 if elmt.tag == 'title' and not
   elmt.text.startswith('Top Stories'):
  printf('- %s' % elmt.text)

這段腳本在2.x和3.x下面運(yùn)行時(shí),不需要做任何改動(dòng),運(yùn)行效果完全一樣,當(dāng)然,如果你正在使用的是2.4或者更老的版本,你需要單獨(dú)下載ElementTree。

但是有時(shí)候感覺(jué)這些改變把你優(yōu)雅的Python代碼弄得一團(tuán)糟,畢竟可讀性才是最重要的,如果你要優(yōu)先保證代碼的整潔而且在不修改任何地方的前提下運(yùn)行在兩個(gè)版本的Python環(huán)境中,那么你可以看一下six包。

six一個(gè)兼容庫(kù),它的主要任務(wù)是提供接口隱藏復(fù)雜的細(xì)節(jié),你可以在這里找到它。無(wú)論你是使用像six這樣的庫(kù)還是用自己的方法來(lái)做,我們希望這個(gè)簡(jiǎn)短的介紹可以讓你開(kāi)始考慮寫(xiě)的代碼能夠在2.x和3.x下同時(shí)運(yùn)行。

相關(guān)文章

  • Python更新數(shù)據(jù)庫(kù)腳本兩種方法及對(duì)比介紹

    Python更新數(shù)據(jù)庫(kù)腳本兩種方法及對(duì)比介紹

    這篇文章給大家介紹了Python更新數(shù)據(jù)庫(kù)腳本兩種方法及數(shù)據(jù)庫(kù)查詢?nèi)N方式,然后在文章下面給大家介紹了兩種方式對(duì)比介紹,非常不錯(cuò),感興趣的朋友參考下吧
    2017-07-07
  • Python繪制詞云圖之可視化神器pyecharts的方法

    Python繪制詞云圖之可視化神器pyecharts的方法

    這篇文章主要介紹了Python繪制詞云圖之可視化神器pyecharts,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • python操作redis的方法

    python操作redis的方法

    這篇文章主要介紹了python操作redis的方法,包括Python針對(duì)redis的連接、設(shè)置、獲取、刪除等常用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • 聊聊python中的循環(huán)遍歷

    聊聊python中的循環(huán)遍歷

    這篇文章主要介紹了python中的循環(huán)遍歷的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)python,感興趣的朋友可以了解下
    2020-09-09
  • 關(guān)于matlab圖像濾波詳解(二維傅里葉濾波)

    關(guān)于matlab圖像濾波詳解(二維傅里葉濾波)

    這篇文章主要介紹了關(guān)于matlab圖像濾波詳解(二維傅里葉濾波),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Pandas使用query()優(yōu)雅的查詢實(shí)例

    Pandas使用query()優(yōu)雅的查詢實(shí)例

    本文主要介紹了Pandas使用query()優(yōu)雅的查詢實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Python日志無(wú)延遲實(shí)時(shí)寫(xiě)入的示例

    Python日志無(wú)延遲實(shí)時(shí)寫(xiě)入的示例

    今天小編就為大家分享一篇Python日志無(wú)延遲實(shí)時(shí)寫(xiě)入的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • Python 文件重命名工具代碼

    Python 文件重命名工具代碼

    Python 文件重命名工具實(shí)現(xiàn)代碼。
    2009-07-07
  • PyCharm安裝PyQt5及其工具(Qt Designer、PyUIC、PyRcc)的步驟詳解

    PyCharm安裝PyQt5及其工具(Qt Designer、PyUIC、PyRcc)的步驟詳解

    這篇文章主要介紹了PyCharm安裝PyQt5及其工具(Qt Designer、PyUIC、PyRcc)的步驟,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Python3.10新特性之match語(yǔ)句示例詳解

    Python3.10新特性之match語(yǔ)句示例詳解

    這篇文章主要為大家介紹了Python3.10新特性之match語(yǔ)句示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02

最新評(píng)論