摘要:注本文的作者是。原文的地址為該筆記向你展示了編寫不會過時的兼容和的代碼風格。它是在的演講,。基本語法差異為了打印出多個。方方和工具沒有提供一個選項自動完成這個。如果你為了個項目編寫新的代碼庫,你可以用一個字符模塊標記所有的字符字面量。
注:本文的作者是 Ed Schofield。原文的地址為: Cheat Sheet: Writing Python 2-3 compatible code
該筆記向你展示了編寫不會過時的兼容 Python 2 和 Python 3 的代碼風格。
它是 Ed Schofield 在 PyCon AU 2014 的演講,“ Writing 2/3 compatible code ”。
最低版本:
Python 2: 2.6+
Python 3: 3.3+
安裝一些下面的 imports 適用于使用 pip 安裝在 PyPI 上安裝:
import future # pip install future import past # pip install past import six # pip install six
以下的腳本也適用于 pip 安裝:
futurize # pip install futurize pasteurize # pip install pasteurize
查看 http://python-future.org 和 https://pythonhosted.org/six/ 獲取更多消息。
基本語法差異print:
# Python 2 only: print "Hello"
# Python 2 and 3: print("Hello")
為了打印出多個 strings。 import print_function 來防止 Py2 把它解釋成一個元組。
# 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="")
拋出異常
# 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"))
異常鏈 (PEP 3134):
# 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)
# Testing the above: try: fd = FileDatabase("non_existent_file.txt") except Exception as e: assert isinstance(e.__cause__, IOError) # FileNotFoundError on Py3.3+ inherits from IOError
捕獲異常:
# Python 2 only: try: ... except ValueError, e: ...
# Python 2 and 3: try: ... except ValueError as e: ...
除法
整除(rounding down):
# Python 2 only: assert 2 / 3 == 0
# Python 2 and 3: assert 2 // 3 == 0
“True division” (float division):
# Python 3 only: assert 3 / 2 == 1.5
# Python 2 and 3: from __future__ import division # (at top of module) assert 3 / 2 == 1.5
“Old division” (i.e. compatible with Py2 behaviour):
# Python 2 only: a = b / c # with any types
# Python 2 and 3: from past.utils import old_div a = old_div(b, c) # always same as / on Py2
長整數
短整數在 Python 3 中已經去除了,并且 long 已經變成了 int(沒有 L 在 repr 后面)
# Python 2 only k = 9223372036854775808L # Python 2 and 3: k = 9223372036854775808
# Python 2 only bigint = 1L # Python 2 and 3 from future.builtins import int bigint = int(1)
為了測試一個值是否是整數(任何類型):
# Python 2 only: if isinstance(x, (int, long)): ... # Python 3 only: if isinstance(x, int): ... # Python 2 and 3: option 1 from future.builtins import int # subclass of long on Py2 if isinstance(x, int): # matches both int and long on Py2 ... # Python 2 and 3: option 2 from past.builtins import long if isinstance(x, (int, long)): ...
八進制常量
0644 # Python 2 only
0o644 # Python 2 and 3
Backtick repr
`x` # Python 2 only
repr(x) # Python 2 and 3
元類
class BaseForm(object): pass class FormType(type): pass
# Python 2 only: class Form(BaseForm): __metaclass__ = FormType pass
# Python 3 only: class Form(BaseForm, metaclass=FormType): pass
# Python 2 and 3: from six import with_metaclass # or from future.utils import with_metaclass class Form(with_metaclass(FormType, BaseForm)): passStrings 和 bytes
Unicode(text) 字符字面量
如果你更新一個已經存在的 Python 2 的代碼庫,為所有的字符字面量使用 u 做前綴作為 unicode 的標記可能會更好。
# Python 2 only s1 = "The Zen of Python" s2 = u"きたないのよりきれいな方がいい " # Python 2 and 3 s1 = u"The Zen of Python" s2 = u"きたないのよりきれいな方がいい "
futurize 和 python-modernize 工具沒有提供一個選項自動完成這個。
如果你為了個項目編寫新的代碼庫,你可以用一個 unicode 字符模塊標記所有的字符字面量。
# Python 2 and 3 from __future__ import unicode_literals # at top of module s1 = "The Zen of Python" s2 = "きたないのよりきれいな方がいい "
查看 http://python-future.org/unicode_literals.html 這里獲取更多的關于討論使用哪種風格的討論。
字節-字符 字面量
# Python 2 only s = "This must be a byte-string" # Python 2 and 3 s = b"This must be a byte-string"
To loop over a byte-string with possible high-bit characters, obtaining each character as a byte-string of length 1:
# Python 2 only: for bytechar in "byte-string with high-bit chars like xf9": ... # Python 3 only: for myint in b"byte-string with high-bit chars like xf9": bytechar = bytes([myint]) # Python 2 and 3: from future.builtins import bytes for myint in bytes(b"byte-string with high-bit chars like xf9"): bytechar = bytes([myint])
chr() 和 .encode("latin-1") 其中的任何一個都可以用于把一個 int 轉換成一個 1-char byte string
# Python 3 only: for myint in b"byte-string with high-bit chars like xf9": char = chr(myint) # returns a unicode string bytechar = char.encode("latin-1") # Python 2 and 3: from future.builtins import bytes, chr for myint in bytes(b"byte-string with high-bit chars like xf9"): char = chr(myint) # returns a unicode string bytechar = char.encode("latin-1") # forces returning a byte str
basestring
# Python 2 only: a = u"abc" b = "def" assert (isinstance(a, basestring) and isinstance(b, basestring)) # Python 2 and 3: alternative 1 from past.builtins import basestring # pip install future a = u"abc" b = b"def" assert (isinstance(a, basestring) and isinstance(b, basestring))
# Python 2 and 3: alternative 2: refactor the code to avoid considering # byte-strings as strings. from future.builtins import str a = u"abc" b = b"def" c = b.decode() assert isinstance(a, str) and isinstance(c, str) # ...
unicode
# Python 2 only: templates = [u"blog/blog_post_detail_%s.html" % unicode(slug)]
# Python 2 and 3: alternative 1 from future.builtins import str templates = [u"blog/blog_post_detail_%s.html" % str(slug)]
# Python 2 and 3: alternative 2 from future.builtins import str as text templates = [u"blog/blog_post_detail_%s.html" % text(slug)]
StringIO
# Python 2 only: from StringIO import StringIO # or: from cStringIO import StringIO # Python 2 and 3: from io import BytesIO # for handling byte strings from io import StringIO # for handling unicode stringsImports relative to a package
假設包的結構是這樣的:
mypackage/ __init__.py submodule1.py submodule2.py
submodule1.py 的代碼如下:
# Python 2 only: import submodule2
# Python 2 and 3: from . import submodule2
# Python 2 and 3: # To make Py2 code safer (more like Py3) by preventing # implicit relative imports, you can also add this to the top: from __future__ import absolute_import字典
heights = {"Fred": 175, "Anne": 166, "Joe": 192}
Iterating through dict keys/values/items
迭代字典的鍵:
# Python 2 only: for key in heights.iterkeys(): ...
# Python 2 and 3: for key in heights: ...
迭代字典的值:
# Python 2 only: for value in heights.itervalues(): ...
# Idiomatic Python 3 for value in heights.values(): # extra memory overhead on Py2 ...
# Python 2 and 3: option 1 from future.builtins import dict heights = dict(Fred=175, Anne=166, Joe=192) for key in heights.values(): # efficient on Py2 and Py3 ...
# Python 2 and 3: option 2 from future.builtins import itervalues # or from six import itervalues for key in itervalues(heights): ...
迭代字典元素:
# Python 2 only: for (key, value) in heights.iteritems(): ...
# Python 2 and 3: option 1 for (key, value) in heights.items(): # inefficient on Py2 ...
# Python 2 and 3: option 2 from future.builtins import iteritems # or from six import iteritems for (key, value) in iteritems(heights): ...
字典的鍵/值/元素 作為一個列表
字典的鍵作為一個列表:
# Python 2 only: keylist = heights.keys() assert isinstance(keylist, list)
# Python 2 and 3: keylist = list(heights) assert isinstance(keylist, list)
字典的值作為一個列表:
# Python 2 only: heights = {"Fred": 175, "Anne": 166, "Joe": 192} valuelist = heights.values() assert isinstance(valuelist, list)
# Python 2 and 3: option 1 valuelist = list(heights.values()) # inefficient on Py2
# Python 2 and 3: option 2 from future.builtins import dict heights = dict(Fred=175, Anne=166, Joe=192) valuelist = list(heights.values())
# Python 2 and 3: option 3 from future.utils import listvalues valuelist = listvalues(heights)
# Python 2 and 3: option 4 from future.utils import itervalues # or from six import itervalues valuelist = list(itervalues(heights))
字典元素作為一個列表:
# Python 2 and 3: option 1 itemlist = list(heights.items()) # inefficient on Py2
# Python 2 and 3: option 2 from future.utils import listitems itemlist = listitems(heights)
# Python 2 and 3: option 3 from future.utils import iteritems # or from six import iteritems itemlist = list(iteritems(heights))自定義類的行為
自定義迭代器:
# Python 2 only class Upper(object): def __init__(self, iterable): self._iter = iter(iterable) def next(self): # Py2-style return self._iter.next().upper() def __iter__(self): return self itr = Upper("hello") assert itr.next() == "H" # Py2-style assert list(itr) == list("ELLO")
# 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")
自定義 __str__ 方法
# Python 2 only: class MyClass(object): def __unicode__(self): return "Unicode string: u5b54u5b50" def __str__(self): return unicode(self).encode("utf-8") a = MyClass() print(a) # prints encoded string
# Python 2 and 3: from future.utils import python_2_unicode_compatible @python_2_unicode_compatible class MyClass(object): def __str__(self): return u"Unicode string: u5b54u5b50" a = MyClass() print(a) # prints string encoded as utf-8 on Py2
Unicode string: 孔子
自定義 __nonzero__ 對比 __bool__ 方法:
# Python 2 only: class AllOrNothing(object): def __init__(self, l): self.l = l def __nonzero__(self): return all(self.l) container = AllOrNothing([0, 100, 200]) assert not bool(container)
# Python 2 and 3: from future.builtins import object class AllOrNothing(object): def __init__(self, l): self.l = l def __bool__(self): return all(self.l) container = AllOrNothing([0, 100, 200]) assert not bool(container)列表對迭代器
xrange:
# 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): ...
range:
# Python 2 only mylist = range(5) assert mylist == [0, 1, 2, 3, 4]
# Python 2 and 3: forward-compatible: option 1 mylist = list(range(5)) # copies memory on Py2 assert mylist == [0, 1, 2, 3, 4]
# Python 2 and 3: forward-compatible: option 2 from future.builtins import range mylist = list(range(5)) assert mylist == [0, 1, 2, 3, 4]
# Python 2 and 3: option 3 from future.utils import lrange mylist = lrange(5) assert mylist == [0, 1, 2, 3, 4]
# Python 2 and 3: backward compatible from past.builtins import range mylist = range(5) assert mylist == [0, 1, 2, 3, 4]
map:
# Python 2 only: mynewlist = map(f, myoldlist) assert mynewlist == [f(x) for x in myoldlist]
# Python 2 and 3: option 1 # Idiomatic Py3, but inefficient on Py2 mynewlist = list(map(f, myoldlist)) assert mynewlist == [f(x) for x in myoldlist]
# Python 2 and 3: option 2 from future.builtins import map mynewlist = list(map(f, myoldlist)) assert mynewlist == [f(x) for x in myoldlist]
# Python 2 and 3: option 3 try: import itertools.imap as map except ImportError: pass mynewlist = list(map(f, myoldlist)) # inefficient on Py2 assert mynewlist == [f(x) for x in myoldlist]
# Python 2 and 3: option 4 from future.utils import lmap mynewlist = lmap(f, myoldlist) assert mynewlist == [f(x) for x in myoldlist]
# Python 2 and 3: option 5 from past.builtins import map mynewlist = map(f, myoldlist) assert mynewlist == [f(x) for x in myoldlist]
imap:
# Python 2 only: from itertools import imap myiter = imap(func, myoldlist) assert isinstance(myiter, iter)
# Python 3 only: myiter = map(func, myoldlist) assert isinstance(myiter, iter)
# Python 2 and 3: option 1 from future.builtins import map myiter = map(func, myoldlist) assert isinstance(myiter, iter)
# Python 2 and 3: option 2 try: import itertools.imap as map except ImportError: pass myiter = map(func, myoldlist) assert isinstance(myiter, iter)
zip, izip
As above with zip and itertools.izip.
filter, ifilter
As above with filter and itertools.ifilter too
其他內建函數File IO with open():
# Python 2 only f = open("myfile.txt") data = f.read() # as a byte string text = data.decode("utf-8") # Python 2 and 3: alternative 1 from io import open f = open("myfile.txt", "rb") data = f.read() # as bytes text = data.decode("utf-8") # unicode, not bytes # Python 2 and 3: alternative 2 from io import open f = open("myfile.txt", encoding="utf-8") text = f.read() # unicode, not bytes
reduce()
# Python 2 only: assert reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) == 1+2+3+4+5
# Python 2 and 3: from functools import reduce assert reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) == 1+2+3+4+5
raw_input()
# Python 2 only: name = raw_input("What is your name? ") assert isinstance(name, str) # native str
# Python 2 and 3: from future.builtins import input name = input("What is your name? ") assert isinstance(name, str) # native str on Py2 and Py3
input()
# Python 2 only: input("Type something safe please: ")
# Python 2 and 3 from future.builtins import input eval(input("Type something safe please: "))
警告:使用上面任何一個都是不安全的
file()
# Python 2 only: f = file(pathname)
# Python 2 and 3: f = open(pathname) # But preferably, use this: from io import open f = open(pathname, "rb") # if f.read() should return bytes # or f = open(pathname, "rt") # if f.read() should return unicode text
execfile()
# Python 2 only: execfile("myfile.py")
# Python 2 and 3: alternative 1 from past.builtins import execfile execfile("myfile.py")
# Python 2 and 3: alternative 2 exec(compile(open("myfile.py").read())) # This can sometimes cause this: # SyntaxError: function ... uses import * and bare exec ... # See https://github.com/PythonCharmers/python-future/issues/37
unichr()
# Python 2 only: assert unichr(8364) == "€"
# Python 3 only: assert chr(8364) == "€"
# Python 2 and 3: from future.builtins import chr assert chr(8364) == "€"
intern()
# Python 2 only: intern("mystring")
# Python 3 only: from sys import intern intern("mystring")
# Python 2 and 3: alternative 1 from past.builtins import intern intern("mystring")
# Python 2 and 3: alternative 2 try: from sys import intern except ImportError: pass intern("mystring")
apply()
args = ("a", "b") kwargs = {"kwarg1": True}
# Python 2 only: apply(f, args, kwargs)
# Python 2 and 3: alternative 1 f(*args, **kwargs)
# Python 2 and 3: alternative 2 from past.builtins import apply apply(f, args, kwargs)
chr()
# Python 2 only: assert chr(64) == b"@" assert chr(200) == b"xc8"
# Python 3 only: option 1 assert chr(64).encode("latin-1") == b"@" assert chr(0xc8).encode("latin-1") == b"xc8"
# Python 2 and 3: option 1 from future.builtins import chr assert chr(64).encode("latin-1") == b"@" assert chr(0xc8).encode("latin-1") == b"xc8"
# Python 3 only: option 2 assert bytes([64]) == b"@" assert bytes([0xc8]) == b"xc8"
# Python 2 and 3: option 2 from future.builtins import bytes assert bytes([64]) == b"@" assert bytes([0xc8]) == b"xc8"
cmp()
# Python 2 only: assert cmp("a", "b") < 0 and cmp("b", "a") > 0 and cmp("c", "c") == 0
# Python 2 and 3: alternative 1 from past.builtins import cmp assert cmp("a", "b") < 0 and cmp("b", "a") > 0 and cmp("c", "c") == 0
# Python 2 and 3: alternative 2 cmp = lambda(x, y): (x > y) - (x < y) assert cmp("a", "b") < 0 and cmp("b", "a") > 0 and cmp("c", "c") == 0
reload()
# Python 2 only: reload(mymodule)
# Python 2 and 3 from imp import reload reload(mymodule)標準庫
StringIO 模塊
# Python 2 only from StringIO import StringIO from cStringIO import StringIO
# Python 2 and 3 from io import BytesIO # and refactor StringIO() calls to BytesIO() if passing byte-strings
http 模塊
# Python 2 only: import httplib import Cookie import cookielib import BaseHTTPServer import SimpleHTTPServer import CGIHttpServer # Python 2 and 3: from future.standard_library import hooks with hooks(): import http.client import http.cookies import http.cookiejar import http.server
urllib 模塊
這個使用 urllib 的示例,相同的模式也適用于其他的已經移除的模塊(一個完整的列表 http://python-future.org/standard_library_imports.html#list-of-standard-library-modules )
# Python 2 only: from urlparse import urlparse from urllib import urlencode
# Python 3 only: from urllib.parse import urlparse, urlencode
# Python 2 and 3: alternative 1 from future.standard_library import hooks with hooks(): from urllib.parse import urlparse, urlencode
# Python 2 and 3: alternative 2 from future.moves.urllib.parse import urlparse, urlencode # or from six.moves.urllib.parse import urlparse, urlencode
# Python 2 and 3: alternative 3 try: from urllib.parse import urlparse, urlencode except ImportError: from urlparse import urlparse from urllib import urlencode
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/37336.html
摘要:年月宣布支持時間延長到年。更詳細的發布列表參閱官網的版本號分為三段,形如。其中表示大版本號,一般當整體重寫,或出現不向后兼容的改變時,增加表示功能更新,出現新功能時增加表示小的改動如修復了某個,只要有修改就增加。年公司正式發布。 < 返回索引頁 Python語言簡介 Python介紹及發展 介紹 Python 官方網站:https://www.python.org/, 大家可以到此處下...
摘要:如果需要在二元運算符周圍做換行操作,例如和,那么需要將換行操作放在前面,這條規則源于數學,數學家同意在二元運算符之前換行以可提高可讀性,比較以下兩個例子。在二元運算符之前換行可以讓代碼更加具有可讀性,所鼓勵這種方式。 原文地址:How to Write Beautiful Python Code With PEP 8 作者:Jasmine Finer 翻譯:howie6879 ...
摘要:作者宋天龍來源科技大本營導語一切都始于年的那個圣誕節,的誕生并不算恰逢其時,它崛起充滿了機遇巧合,也有其必然性。年的圣誕節,開始編寫語言的編譯器。年發布的標志著的框架基本確定。年月發布了系列的最后一個版本,主版本號為。 showImg(https://segmentfault.com/img/remote/1460000019862276); 作者 | 宋天龍來源 | AI科技大本營 ...
摘要:編程基礎要學習如何用進行數據分析,數據分析師建議第一步是要了解一些的編程基礎,知道的數據結構,什么是向量列表數組字典等等了解的各種函數及模塊。數據分析師認為數據分析有的工作都在處理數據。 showImg(https://segmentfault.com/img/bVbnbZo?w=1024&h=653); 本文為CDA數據分析研究院原創作品,轉載需授權 1.為什么選擇Python進行數...
摘要:首發于我的博客線程池進程池網絡編程之同步異步阻塞非阻塞后端掘金本文為作者原創,轉載請先與作者聯系。在了解的數據結構時,容器可迭代對象迭代器使用進行并發編程篇二掘金我們今天繼續深入學習。 Python 算法實戰系列之棧 - 后端 - 掘金原文出處: 安生??? 棧(stack)又稱之為堆棧是一個特殊的有序表,其插入和刪除操作都在棧頂進行操作,并且按照先進后出,后進先出的規則進行運作。 如...
閱讀 2085·2021-10-11 10:59
閱讀 936·2021-09-23 11:21
閱讀 3568·2021-09-06 15:02
閱讀 1621·2021-08-19 10:25
閱讀 3379·2021-07-30 11:59
閱讀 2375·2019-08-30 11:27
閱讀 2588·2019-08-30 11:20
閱讀 2978·2019-08-29 13:15