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

資訊專(zhuān)欄INFORMATION COLUMN

淺談 (x, y) = (y, x)

AprilJ / 2083人閱讀

摘要:常用的模塊方法接收參數(shù)為一個(gè)代碼塊可以是模塊,類(lèi),方法,函數(shù),或者是對(duì)象,可以得到這個(gè)代碼塊對(duì)應(yīng)的字節(jié)碼指令序列。具體驗(yàn)證可以分析下兩種方法的字節(jié)碼指令。

交換兩個(gè)變量的值,大家最常見(jiàn)的寫(xiě)法是這樣的:

>>> temp = x
>>> x = y
>>> y = temp

但其實(shí)更 Pythonic 的寫(xiě)法是這樣的:

>>> x, y = y, x

大家有沒(méi)有想過(guò)為什么在 Python 中可以這樣交換兩個(gè)變量的值?

Python 代碼是先解釋?zhuān)ㄟ@里的解釋是相對(duì)編譯而言的,Python 不同與 C/C++ 之類(lèi)的編譯型語(yǔ)言,是需要從源文件編譯成機(jī)器指令)成 Python 字節(jié)碼(byte code, .pyc文件主要是用來(lái)存儲(chǔ)這些字節(jié)碼的)之后,再由 Python 解釋器來(lái)執(zhí)行這些字節(jié)碼的。一般來(lái)說(shuō),Python 語(yǔ)句會(huì)對(duì)應(yīng)若干字節(jié)碼指令,Python 的字節(jié)碼類(lèi)似于匯編指令的中間語(yǔ)言,但是一個(gè)字節(jié)碼并不只是對(duì)應(yīng)一個(gè)機(jī)器指定。

內(nèi)置模塊 dis 可以用來(lái)分析字節(jié)碼。DOC

The dis module supports the analysis of CPython bytecode by disassembling it. The CPython bytecode which this module takes as an input is defined in the file Include/opcode.h and used by the compiler and the interpreter.

常用的 dis 模塊方法: dis.dis([bytesource])

dis.dis([bytesource])
Disassemble the bytesource object. bytesource can denote either a module, a class, a method, a function, or a code object. For a module, it disassembles all functions. For a class, it disassembles all methods. For a single code sequence, it prints one line per bytecode instruction. If no object is provided, it disassembles the last traceback.

dis.dis 接收參數(shù)為一個(gè)代碼塊(可以是模塊,類(lèi),方法,函數(shù),或者是對(duì)象),可以得到這個(gè)代碼塊對(duì)應(yīng)的字節(jié)碼指令序列。

>>> import dis
>>> def test():
...     a = 1
...     
... 
>>> dis.dis(test)
  3           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (a)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        

輸出的格式分別是:行號(hào),地址,指令,操作參數(shù), 參數(shù)解釋?zhuān)ㄗR(shí)別變量名稱(chēng),常量值等)

切入正題, 我們直接來(lái)看下第二種寫(xiě)法的字節(jié)碼指令:

swap_2.py

x = 1
y = 3
x, y = y, x

python -m dis swap_2.py

  1           0 LOAD_CONST               0 (1)
              3 STORE_NAME               0 (x)

  2           6 LOAD_CONST               1 (3)
              9 STORE_NAME               1 (y)

  3          12 LOAD_NAME                1 (y)
             15 LOAD_NAME                0 (x)
             18 ROT_TWO
             19 STORE_NAME               0 (x)
             22 STORE_NAME               1 (y)
             25 LOAD_CONST               2 (None)
             28 RETURN_VALUE

部分字節(jié)碼指令如下,具體的指令請(qǐng)移步官網(wǎng):

LOAD_CONST(consti)
Pushes co_consts[consti] onto the stack.
STORE_NAME(namei)
Implements name = TOS. namei is the index of name in the attribute co_names of the code object. The compiler tries to use STORE_FAST or STORE_GLOBAL if possible.
LOAD_NAME(namei)
Pushes the value associated with co_names[namei] onto the stack.
ROT_TWO()
Swaps the two top-most stack items.

解釋下上面的字節(jié)碼指令:

第一行執(zhí)行兩個(gè)字節(jié)碼指令, 分別是LOAD_CONSTSTORE_NAME,執(zhí)行的動(dòng)作是將 co_consts[0] 壓棧(也就是常量表的第一個(gè)常量,整數(shù)1壓入棧中),然后獲取co_names[0]的變量名x(變量名表的第一個(gè)名字),棧頂元素(整數(shù)1)出棧和co_names[0]存儲(chǔ)到f->f_locals。

第二行的執(zhí)行方式如同第一行。

co_consts[0] = 1
co_names[0] = x
f->f_locals["x"] = 1

co_consts[1] = 3
co_names[1] = y
f->f_locals["y"] = 3

重點(diǎn)在第三行,前兩行的計(jì)算順序都是從友往左進(jìn)行的(一般情況下, Python 表達(dá)式的計(jì)算順序是從左到右,但是在表達(dá)式賦值的時(shí)候,表達(dá)式右邊的操作數(shù)優(yōu)先于左邊),也就是說(shuō),第四行是這樣執(zhí)行的,先創(chuàng)建元組(y, x),執(zhí)行的動(dòng)作是兩個(gè) LOAD_NAME,會(huì)依次搜索local,global,builtin名字空間中的co_names[1](對(duì)應(yīng)變量名y)和co_names[0](對(duì)應(yīng)變量名x)并把相對(duì)應(yīng)的值壓棧。接下去執(zhí)行的動(dòng)作是交換ROT_TWO, 交換棧頂?shù)膬蓚€(gè)元素位置。

從下一個(gè)執(zhí)行指令就可以看出來(lái),先獲取co_names[0]的變量名x,棧頂元素(現(xiàn)在是原先y的值)出棧并儲(chǔ)存,兩次存儲(chǔ)就實(shí)現(xiàn)了交換兩個(gè)變量的值。

第二種方法不借助任何中間變量并且能夠獲得更好的性能。我們可以簡(jiǎn)單測(cè)試下:

>>> from timeit import Timer
>>> Timer("temp = x;x = y;y = temp", "x=2;y=3").timeit()
0.030814170837402344
>>> Timer("x, y = y, x", "x=2;y=3").timeit()
0.027340173721313477

為什么第二種方法消耗的時(shí)間更少呢?可以猜測(cè)一下,是中間變量賦值引起的耗時(shí)。具體驗(yàn)證可以分析下兩種方法的字節(jié)碼指令。

Life such short,be Pythonic .

Blog : JunNplus

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

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

相關(guān)文章

  • 淺談js中的閉包

    摘要:對(duì)于一個(gè)個(gè)剛剛接觸前端的新手,天天聽(tīng)人講閉包,聽(tīng)的那個(gè)高大尚,心中對(duì)各位技術(shù)大佬是那個(gè)的膜拜,于是做為前端菜鳥(niǎo)的我,就去了解了傳說(shuō)中的閉包。 對(duì)于一個(gè)個(gè)剛剛接觸前端的新手,天天聽(tīng)人講閉包,聽(tīng)的那個(gè)高大尚,心中對(duì)各位技術(shù)大佬是那個(gè)的膜拜,于是做為前端菜鳥(niǎo)的我,就去了解了傳說(shuō)中的閉包。 何為閉包?通俗易懂的講,就是可以調(diào)用函數(shù)內(nèi)部的變量和方法 舉例說(shuō)明如下: function t...

    kumfo 評(píng)論0 收藏0
  • Python之淺談exec()函數(shù)

    摘要:本次分享講簡(jiǎn)單聊聊函數(shù)的用法,希望能給讀者一點(diǎn)啟示和參考。在最后的語(yǔ)句中,我們給出了的值,并且值重復(fù),函數(shù)接收后面一個(gè)值,且值傳遞不起作用,因此輸出結(jié)果為本次分享到此結(jié)束。本文介紹了幾個(gè)函數(shù)使用的例子,希望能拋磚引玉,也歡迎大家多多交流 ??在Python中,exec()是一個(gè)十分有趣且實(shí)用的內(nèi)置函數(shù),不同于eval()函數(shù)只能執(zhí)行計(jì)算數(shù)學(xué)表達(dá)式的結(jié)果的功能,exec()能夠動(dòng)態(tài)地執(zhí)行...

    hedzr 評(píng)論0 收藏0
  • 淺談深拷貝和淺拷貝

    摘要:而引用類(lèi)型值是指那些保存堆內(nèi)存中的對(duì)象,意思是變量中保存的實(shí)際上只是一個(gè)指針,這個(gè)指針指向內(nèi)存中的另一個(gè)位置,該位置保存對(duì)象。而堆內(nèi)存主要負(fù)責(zé)對(duì)象這種變量類(lèi)型的存儲(chǔ)。我們需要明確一點(diǎn),深拷貝與淺拷貝的概念只存在于引用類(lèi)型。 深拷貝和淺拷貝 說(shuō)起深拷貝和淺拷貝,首先我們來(lái)看兩個(gè)栗子 // 栗子1 var a = 1,b=a; console.log(a); console.log(b) ...

    littleGrow 評(píng)論0 收藏0
  • 淺談 python 中的 sorted()與sort()

    摘要:返回值是一個(gè)經(jīng)過(guò)排序的可迭代類(lèi)型,與一樣。注一般來(lái)說(shuō),和可以使用表達(dá)式。與的不同在于,是在原位重新排列列表,而是產(chǎn)生一個(gè)新的列表。 我們需要對(duì)List進(jìn)行排序,Python提供了兩個(gè)方法 對(duì)給定的List L進(jìn)行排序,方法1.用List的成員函數(shù)sort進(jìn)行排序方法2.用built-in函數(shù)sorted進(jìn)行排序(從2.4開(kāi)始) ----------------------------...

    lansheng228 評(píng)論0 收藏0
  • 由 sort 中 key 的用法淺談 python

    摘要:但是實(shí)際寫(xiě)程序中,我們經(jīng)常會(huì)寫(xiě)出許多繁雜的丑陋的代碼。特別推薦,許多代碼讓我獲益匪淺,比如這里對(duì)的使用。用可以寫(xiě)出很簡(jiǎn)單直觀的代碼,如下當(dāng)然,上面不考慮效率,這里有一個(gè)利用分治法思想的高效的方法。更多文章更多閱讀中參數(shù)的用法高級(jí)編程技巧 用 Python 時(shí)間也算不短了,但總感覺(jué)自己在用寫(xiě) C++ 代碼的思維寫(xiě) Python,沒(méi)有真正用到其作為腳本語(yǔ)言的優(yōu)勢(shì)。之前刷 LeetCode ...

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

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

0條評(píng)論

閱讀需要支付1元查看
<