python之six用法

前言

最近在寫一個(gè)django的項(xiàng)目压语,在form的底層函數(shù)當(dāng)中看見了six的使用格仲,就來學(xué)習(xí)一下吱晒。也希望寫的這些東西能夠更好的幫助大家學(xué)習(xí)django的一些高級用法财著、理解django的一些源碼联四。

通過寫這篇文章,也是希望幫助本人了解python2和python3之間的一些差別撑教,也希望這篇文章能夠幫助到更多的人學(xué)習(xí)python朝墩。

對于部分既能在python2中也能在python3中使用的函數(shù),并沒有特殊說明伟姐,僅在代碼示例中進(jìn)行了相關(guān)的測試收苏,也請大家注意一下~后續(xù)有時(shí)間會對整體進(jìn)行修改~

關(guān)于python2和python3中的區(qū)別,也可以參考如下資料:

  1. python函數(shù)方法屬性愤兵、模塊變量不同

本文中使用的python2的版本是2.7.13鹿霸, python3的版本是3.6.1。由于本人能力有限秆乳,文中如有錯(cuò)誤懦鼠,歡迎指正。

運(yùn)行環(huán)境

six.PY2 返回一個(gè)表示當(dāng)前運(yùn)行環(huán)境是否為python2的boolean值

six.PY3 返回一個(gè)表示當(dāng)前運(yùn)行環(huán)境是否為python3的boolean值

源碼解析:

# Useful for very coarse version differentiation.
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
PY34 = sys.version_info[0:2] >= (3, 4)

常量

six.class_types

這里主要是針對python中的old-style和new-style, new-style為type, old-style為 types.ClassType。

python2中同時(shí)有old-style和new-style葛闷,python3中只有new-style憋槐。

具體的區(qū)別可以參考What is the difference between old style and new style classes in Python?

six.integer_types

這里針對python2和python3中各自支持的int類型進(jìn)行了區(qū)分:在python2中双藕,存在 int 和 long 兩種整數(shù)類型淑趾;在python3中,僅存在一種類型int忧陪。

six.string_types

這里針對python2和python3中各自的string類型進(jìn)行了區(qū)分:在python2中扣泊,使用的為basestring;在python3中嘶摊,使用的為str延蟹。

six.text_type

這里針對python2和python3中的文本字符進(jìn)行了區(qū)分:在python2中,使用的文本字符的類型為unicode叶堆;在python3中使用的文本字符的類型為str阱飘。

具體可以參考Python2 與 Python3 的編碼對比

six.binary_type

這里針對python2和python3中的字節(jié)序列進(jìn)行了區(qū)分:在python2中,使用的字節(jié)序列的類型為str虱颗;在python3中使用的字節(jié)序列的類型為bytes沥匈。

具體可以參考Python2 與 Python3 的編碼對比

six.MAXSIZE

list、string忘渔、dict以及其他的容器所能支持的最大尺寸高帖。

if PY3:
    string_types = str,
    integer_types = int,
    class_types = type,
    text_type = str
    binary_type = bytes

    MAXSIZE = sys.maxsize
else:
    string_types = basestring,
    integer_types = (int, long)
    class_types = (type, types.ClassType)
    text_type = unicode
    binary_type = str

    if sys.platform.startswith("java"):
        # Jython always uses 32 bits.
        MAXSIZE = int((1 << 31) - 1)
    else:
        # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
        class X(object):

            def __len__(self):
                return 1 << 31
        try:
            len(X())
        except OverflowError:
            # 32-bit
            MAXSIZE = int((1 << 31) - 1)
        else:
            # 64-bit
            MAXSIZE = int((1 << 63) - 1)
        del X

對象模型兼容

six.get_unbound_function(meth)

針對python2和python3中unbound function的支持不同,在python2中存在unbound function畦粮,在python3中不存在unbound function散址。

if PY3:
    def get_unbound_function(unbound):
        return unbound
else:
    def get_unbound_function(unbound):
        return unbound.im_func

有關(guān)的測試代碼如下:

>>> class Foo():
...     def bar():
...             print(1)
...     def too(self):
...             print(2)
...
>>>

在python2的環(huán)境中:

>>> Foo.bar
<unbound method Foo.bar>
>>> Foo().bar
<bound method Foo.bar of <__main__.Foo instance at 0x10e8a7998>>
>>> Foo.too
<unbound method Foo.too>
>>> Foo().too
<bound method Foo.too of <__main__.Foo instance at 0x10e8a7998>>

在python3的環(huán)境中:

>>> Foo.bar
<function Foo.bar at 0x10ebe4bf8>
>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x10ebeaa58>>
>>> Foo.too
<function Foo.too at 0x10ebe4c80>
>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x10ebeaa58>>

使用six.get_unbound_function(meth):

在python2環(huán)境中:

>>> import six
>>> six.get_unbound_function(Foo.too)
<function too at 0x10e89faa0>
>>> six.get_unbound_function(Foo.bar)
<function bar at 0x10e89fa28>

在python3環(huán)境中:

>>> import six
>>> six.get_unbound_function(Foo.too)
<function Foo.too at 0x10a158c80>
>>> six.get_unbound_function(Foo.bar)
<function Foo.bar at 0x10a158bf8>

six.get_method_function(meth)

此方法可以在方法對象之外得到函數(shù)。在python2中使用im_func, 在python3中使用func宣赔。

if PY3:
    _meth_func = "__func__"
else:
    _meth_func = "im_func"
get_method_function = operator.attrgetter(_meth_func)

有關(guān)的測試代碼如下:

>>> class Foo():
...     def bar():
...             print(1)
...     def too(self):
...             print(2)
...
>>>

在python2環(huán)境中:

>>> import six
>>> six.get_method_function(Foo().bar)
<function bar at 0x10c8c6a28>
>>> six.get_method_function(Foo.bar)
<function bar at 0x10c8c6a28>
>>> six.get_method_function(Foo().too)
<function too at 0x10c8c6aa0>
>>> six.get_method_function(Foo.too)
<function too at 0x10c8c6aa0>

在python3環(huán)境中:

>>> import six
>>> six.get_method_function(Foo.bar)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__func__'
>>> six.get_method_function(Foo().bar)
<function Foo.bar at 0x1047dbbf8>
>>> six.get_method_function(Foo.too)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__func__'
>>> six.get_method_function(Foo().too)
<function Foo.too at 0x1047dbc80>

six.get_method_self(meth)

針對python2以及python3中的不同预麸,返回bound method的self。其中:python2中使用im_self儒将,python3中使用__self__师崎。

if PY3:
    _meth_self = "__self__"
else:
    _meth_self = "im_self"
get_method_self = operator.attrgetter(_meth_self)

有關(guān)的測試代碼如下:

>>> class Foo():
...     def bar():
...             print(1)
...     def too(self):
...             print(2)
...
>>>

在python2的環(huán)境中:

>>> import six
>>> six.get_method_self(Foo.bar)
>>> a = six.get_method_self(Foo.bar)
>>> a
>>> six.get_method_self(Foo().bar)
<__main__.Foo instance at 0x10563da70>
>>> a = six.get_method_self(Foo().bar)
>>> a
<__main__.Foo instance at 0x10563dd88>
>>> six.get_method_self(Foo.too)
>>> a = six.get_method_self(Foo.too)
>>> a
>>> six.get_method_self(Foo().too)
<__main__.Foo instance at 0x10563da28>
>>> a = six.get_method_self(Foo().too)
>>> a
<__main__.Foo instance at 0x10563da70>

在python3的環(huán)境中:

>>> import six
>>> six.get_method_self(Foo.bar)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__self__'
>>> six.get_method_self(Foo().bar)
<__main__.Foo object at 0x1059bbb00>
>>> six.get_method_self(Foo.too)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__self__'
>>> six.get_method_self(Foo().too)
<__main__.Foo object at 0x1059bbb38>

six.get_function_closure(func)

針對python2和python3中的不同,返回函數(shù)當(dāng)中的閉包椅棺。其中犁罩,python2使用func_closure,python3使用 __closure__两疚。

if PY3:
    _func_closure = "__closure__"
else:
    _func_closure = "func_closure"
    
get_function_closure = operator.attrgetter(_func_closure)

關(guān)于閉包的理解可以參考:

  1. 淺顯理解 Python 閉包
  2. 閉包的概念床估、形式與應(yīng)用

有關(guān)的測試代碼如下:

>>> def foo(n):
...     a = 1
...     def bar(n):
...             return a-n
...     return bar

此處需要注意的是foo函數(shù)返回的是bar函數(shù),而不是具體的值诱渤。

在python2的環(huán)境當(dāng)中:

>>> foo.__closure__
>>> foo(1)
<function bar at 0x10c25aa28>
>>> foo(1).__closure__
(<cell at 0x10c25eb40: int object at 0x7f9460d0bca8>,)
>>> foo(1).func_closure
(<cell at 0x10c25ed70: int object at 0x7f9460d0bca8>,)

在python3的環(huán)境當(dāng)中:

>>> foo.__closure__
>>> foo(1)
<function foo.<locals>.bar at 0x10c46dbf8>
>>> foo(1).__closure__
(<cell at 0x10c451198: int object at 0x10be73170>,)
>>> foo(1).func_closure
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'func_closure'

six.get_function_code(func)

針對python2和python3中獲取func中的code對象丐巫,將使用不同的方式進(jìn)行獲取。在python2中,將使用func_code递胧;在python3中碑韵,將使用__code__。

if PY3:
    _func_code = "__code__"
else:
    _func_code = "func_code"
get_function_code = operator.attrgetter(_func_code)

如果你對其中的code object是什么比較感興趣缎脾,可以參考下面的資料:

  1. Exploring Python Code Objects

有關(guān)的測試代碼如下:

>>> def boo():
...     return 1

在python2的環(huán)境當(dāng)中:

>>> boo.func_code
<code object boo at 0x1101092b0, file "<stdin>", line 1>
>>> boo().func_code
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'func_code'

在python3的環(huán)境當(dāng)中:

>>> boo.__code__
<code object boo at 0x104d8a930, file "<stdin>", line 1>
>>> boo().__code__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__code__'

six.get_function_defaults(func)

針對python2和python3中的區(qū)別祝闻,獲取func中的默認(rèn)元組。在python2中遗菠,使用func_defaults联喘;在python3中,使用__defaults__辙纬。

if PY3:
    _func_defaults = "__defaults__"
else:
    _func_defaults = "func_defaults"
get_function_defaults = operator.attrgetter(_func_defaults)

有關(guān)的測試代碼如下:

>>> def boo(a=1):
...     return a
...

在python2環(huán)境中:

>>> boo.func_defaults
(1,)
>>> boo.__defaults__
(1,)
>>> boo().func_defaults
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'func_defaults'
>>> boo().__defaults__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__defaults__'

在python3環(huán)境中:

>>> boo.__defaults__
(1,)
>>> boo.func_defaults
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'func_defaults'
>>> boo().__defaults__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__defaults__'
>>> boo().func_defaults
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'func_defaults'

six.get_function_globals(func)

獲取函數(shù)當(dāng)中的全局變量豁遭。在python2中,使用func_globals贺拣;在python3中蓖谢,使用__globals__。

if PY3:
    _func_globals = "__globals__"
else:
    _func_globals = "func_globals"
get_function_globals = operator.attrgetter(_func_globals)

有關(guān)的測試代碼:

>>> def boo(a=1):
...     x = 100
...     b = x - a
...     return b

在python2環(huán)境中:

>>> boo.__globals__
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'boo': <function boo at 0x109a6e9b0>, '__doc__': None, '__package__': None}
>>> boo.func_globals
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'boo': <function boo at 0x109a6e9b0>, '__doc__': None, '__package__': None}

在python3環(huán)境中:

>>> boo.__globals__
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'boo': <function boo at 0x1029d8e18>}
>>> boo.func_globals
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'func_globals'

six.next(it) or six.advance_iterator(it)

獲取到迭代器的下一個(gè)譬涡。在python2環(huán)境中闪幽,使用it.next();在python3環(huán)境中昂儒,使用next(it)

try:
    advance_iterator = next
except NameError:
    def advance_iterator(it):
        return it.next()
next = advance_iterator

關(guān)于迭代器的內(nèi)容可以參考一下文件:

  1. 迭代器

在python2環(huán)境中:

>>> it = iter([1,2,3,4,5])
>>> while True:
...     try:
...             x = it.next()
...     except NameError:
...             print "name error"
...     except StopIteration:
...             print "end"
...             break
...
end

>>> it = iter([1,2,3,4,5])
>>> while True:
...     try:
...             x = next(it)
...     except NameError:
...             print "name error"
...     except StopIteration:
...             print "end"
...             break
...
end

在python3環(huán)境中:

>>> it = iter([1,2,3,4,5])
>>> while True:
...     try:
...             x = it.next()
...     except NameError:
...             print("name error")
...     except StopIteration:
...             print("end")
...             break
...
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
AttributeError: 'list_iterator' object has no attribute 'next'

>>> it = iter([1,2,3,4,5])
>>> while True:
...     try:
...             x = next(it)
...     except NameError:
...             print("name error")
...     except StopIteration:
...             print("end")
...             break
...
end

six.callable(obj)

該方法用來檢驗(yàn)obj是否可以進(jìn)行調(diào)用沟使。

關(guān)于python的callable屬性,請參考一下文件:

  1. python函數(shù)每日一講 - callable(object)
try:
    callable = callable
except NameError:
    def callable(obj):
        return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)

有關(guān)的測試代碼:

>>> def add(x, y):
...     return x + y
...

在python2環(huán)境中:

>>> callable(add)
True

在python 3.1環(huán)境中:

>>> callable(add)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'callable' is not defined

在python3.2之后的環(huán)境中:

>>> callable(add)
True

未完待續(xù)~~

結(jié)尾

本文是作者在自己空閑的時(shí)間寫的渊跋,如需轉(zhuǎn)載請注明出處腊嗡,謝謝~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市拾酝,隨后出現(xiàn)的幾起案子燕少,更是在濱河造成了極大的恐慌,老刑警劉巖蒿囤,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件客们,死亡現(xiàn)場離奇詭異,居然都是意外死亡材诽,警方通過查閱死者的電腦和手機(jī)底挫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脸侥,“玉大人建邓,你說我怎么就攤上這事≌稣恚” “怎么了官边?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵沸手,是天一觀的道長。 經(jīng)常有香客問我注簿,道長契吉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任诡渴,我火速辦了婚禮捐晶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玩徊。我一直安慰自己租悄,他們只是感情好谨究,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布恩袱。 她就那樣靜靜地躺著,像睡著了一般胶哲。 火紅的嫁衣襯著肌膚如雪畔塔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天鸯屿,我揣著相機(jī)與錄音澈吨,去河邊找鬼。 笑死寄摆,一個(gè)胖子當(dāng)著我的面吹牛谅辣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播婶恼,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼桑阶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了勾邦?” 一聲冷哼從身側(cè)響起蚣录,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎眷篇,沒想到半個(gè)月后萎河,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蕉饼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年虐杯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昧港。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡擎椰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出慨飘,到底是詐尸還是另有隱情确憨,我是刑警寧澤译荞,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站休弃,受9級特大地震影響吞歼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜塔猾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一篙骡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧丈甸,春花似錦糯俗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至顿仇,卻和暖如春淘正,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背臼闻。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工鸿吆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人述呐。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓惩淳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親乓搬。 傳聞我的和親對象是個(gè)殘疾皇子思犁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容