日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Python字节码介绍

發布時間:2023/11/28 生活经验 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python字节码介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

了解 Python 字節碼是什么,Python 如何使用它來執行你的代碼,以及知道它是如何幫到你的。
如果你曾經編寫過 Python,或者只是使用過 Python,你或許經常會看到 Python 源代碼文件——它們的名字以?.py?結尾。你可能還看到過其它類型的文件,比如以?.pyc?結尾的文件,或許你可能聽說過它們就是 Python 的 “字節碼bytecode” 文件。(在 Python 3 上這些可能不容易看到 —— 因為它們與你的?.py?文件不在同一個目錄下,它們在一個叫?__pycache__?的子目錄中)或者你也聽說過,這是節省時間的一種方法,它可以避免每次運行 Python 時去重新解析源代碼。

但是,除了 “噢,原來這就是 Python 字節碼” 之外,你還知道這些文件能做什么嗎?以及 Python 是如何使用它們的?

如果你不知道,那你走運了!今天我將帶你了解 Python 的字節碼是什么,Python 如何使用它去運行你的代碼,以及知道它是如何幫助你的。

Python 如何工作
Python 經常被介紹為它是一個解釋型語言 —— 其中一個原因是在程序運行時,你的源代碼被轉換成 CPU 的原生指令 —— 但這樣的看法只是部分正確。Python 與大多數解釋型語言一樣,確實是將源代碼編譯為一組虛擬機指令,并且 Python 解釋器是針對相應的虛擬機實現的。這種中間格式被稱為 “字節碼”。

因此,這些?.pyc?文件是 Python 悄悄留下的,是為了讓它們運行的 “更快”,或者是針對你的源代碼的 “優化” 版本;它們是你的程序在 Python 虛擬機上運行的字節碼指令。

我們來看一個示例。這里是用 Python 寫的經典程序 “Hello, World!”:

?

下面是轉換后的字節碼(轉換為人類可讀的格式):

?

如果你輸入那個?hello()?函數,然后使用?CPython?解釋器去運行它,那么上述列出的內容就是 Python 所運行的。它看起來可能有點奇怪,因此,我們來深入了解一下它都做了些什么。

Python 虛擬機內幕
CPython 使用一個基于棧的虛擬機。也就是說,它完全面向棧數據結構的(你可以 “推入” 一個東西到棧 “頂”,或者,從棧 “頂” 上 “彈出” 一個東西來)。

CPython 使用三種類型的棧:

調用棧call stack。這是運行 Python 程序的主要結構。它為每個當前活動的函數調用使用了一個東西 —— “幀frame”,棧底是程序的入口點。每個函數調用推送一個新的幀到調用棧,每當函數調用返回后,這個幀被銷毀。
在每個幀中,有一個計算棧evaluation stack (也稱為數據棧data stack)。這個棧就是 Python 函數運行的地方,運行的 Python 代碼大多數是由推入到這個棧中的東西組成的,操作它們,然后在返回后銷毀它們。
在每個幀中,還有一個塊棧block stack。它被 Python 用于去跟蹤某些類型的控制結構:循環、try?/?except?塊、以及?with?塊,全部推入到塊棧中,當你退出這些控制結構時,塊棧被銷毀。這將幫助 Python 了解任意給定時刻哪個塊是活動的,比如,一個?continue?或者?break?語句可能影響正確的塊。
大多數 Python 字節碼指令操作的是當前調用棧幀的計算棧,雖然,還有一些指令可以做其它的事情(比如跳轉到指定指令,或者操作塊棧)。

為了更好地理解,假設我們有一些調用函數的代碼,比如這個:my_function(my_variable, 2)。Python 將轉換為一系列字節碼指令:

一個?LOAD_NAME?指令去查找函數對象?my_function,然后將它推入到計算棧的頂部
另一個?LOAD_NAME?指令去查找變量?my_variable,然后將它推入到計算棧的頂部
一個?LOAD_CONST?指令去推入一個實整數值?2?到計算棧的頂部
一個?CALL_FUNCTION?指令
這個?CALL_FUNCTION?指令將有 2 個參數,它表示那個 Python 需要從棧頂彈出兩個位置參數;然后函數將在它上面進行調用,并且它也同時被彈出(對于函數涉及的關鍵字參數,它使用另一個不同的指令 ——?CALL_FUNCTION_KW,但使用的操作原則類似,以及第三個指令 ——?CALL_FUNCTION_EX,它適用于函數調用涉及到參數使用?*?或?**?操作符的情況)。一旦 Python 擁有了這些之后,它將在調用棧上分配一個新幀,填充到函數調用的本地變量上,然后,運行那個幀內的?my_function?字節碼。運行完成后,這個幀將被調用棧銷毀,而在最初的幀內,my_function?的返回值將被推入到計算棧的頂部。

訪問和理解 Python 字節碼
如果你想玩轉字節碼,那么,Python 標準庫中的?dis?模塊將對你有非常大的幫助;dis?模塊為 Python 字節碼提供了一個 “反匯編”,它可以讓你更容易地得到一個人類可讀的版本,以及查找各種字節碼指令。dis?模塊的文檔?可以讓你遍歷它的內容,并且提供一個字節碼指令能夠做什么和有什么樣的參數的完整清單。

例如,獲取上面的?hello()?函數的列表,可以在一個 Python 解析器中輸入如下內容,然后運行它:

?

函數?dis.dis()?將反匯編一個函數、方法、類、模塊、編譯過的 Python 代碼對象、或者字符串包含的源代碼,以及顯示出一個人類可讀的版本。dis?模塊中另一個方便的功能是?distb()。你可以給它傳遞一個 Python 追溯對象,或者在發生預期外情況時調用它,然后它將在發生預期外情況時反匯編調用棧上最頂端的函數,并顯示它的字節碼,以及插入一個指向到引發意外情況的指令的指針。

它也可以用于查看 Python 為每個函數構建的編譯后的代碼對象,因為運行一個函數將會用到這些代碼對象的屬性。這里有一個查看?hello()?函數的示例:

?

代碼對象在函數中可以以屬性?__code__?來訪問,并且攜帶了一些重要的屬性:

co_consts?是存在于函數體內的任意實數的元組
co_varnames?是函數體內使用的包含任意本地變量名字的元組
co_names?是在函數體內引用的任意非本地名字的元組
許多字節碼指令 —— 尤其是那些推入到棧中的加載值,或者在變量和屬性中的存儲值 —— 在這些元組中的索引作為它們參數。

因此,現在我們能夠理解?hello()?函數中所列出的字節碼:

LOAD_GLOBAL 0:告訴 Python 通過?co_names?(它是?print?函數)的索引 0 上的名字去查找它指向的全局對象,然后將它推入到計算棧
LOAD_CONST 1:帶入?co_consts?在索引 1 上的字面值,并將它推入(索引 0 上的字面值是?None,它表示在?co_consts?中,因為 Python 函數調用有一個隱式的返回值?None,如果沒有顯式的返回表達式,就返回這個隱式的值 )。
CALL_FUNCTION 1:告訴 Python 去調用一個函數;它需要從棧中彈出一個位置參數,然后,新的棧頂將被函數調用。
“原始的” 字節碼 —— 是非人類可讀格式的字節 —— 也可以在代碼對象上作為?co_code屬性可用。如果你有興趣嘗試手工反匯編一個函數時,你可以從它們的十進制字節值中,使用列出?dis.opname?的方式去查看字節碼指令的名字。

字節碼的用處
現在,你已經了解的足夠多了,你可能會想 “OK,我認為它很酷,但是知道這些有什么實際價值呢?”由于對它很好奇,我們去了解它,但是除了好奇之外,Python 字節碼在幾個方面還是非常有用的。

首先,理解 Python 的運行模型可以幫你更好地理解你的代碼。人們都開玩笑說,C 是一種 “可移植匯編器”,你可以很好地猜測出一段 C 代碼轉換成什么樣的機器指令。理解 Python 字節碼之后,你在使用 Python 時也具備同樣的能力 —— 如果你能預料到你的 Python 源代碼將被轉換成什么樣的字節碼,那么你可以知道如何更好地寫和優化 Python 源代碼。

第二,理解字節碼可以幫你更好地回答有關 Python 的問題。比如,我經常看到一些 Python 新手困惑為什么某些結構比其它結構運行的更快(比如,為什么?{}?比?dict()?快)。知道如何去訪問和閱讀 Python 字節碼將讓你很容易回答這樣的問題(嘗試對比一下:?dis.dis("{}")?與?dis.dis("dict()")?就會明白)。

最后,理解字節碼和 Python 如何運行它,為 Python 程序員不經常使用的一種特定的編程方式提供了有用的視角:面向棧的編程。如果你以前從來沒有使用過像 FORTH 或 Fator 這樣的面向棧的編程語言,它們可能有些古老,但是,如果你不熟悉這種方法,學習有關 Python 字節碼的知識,以及理解面向棧的編程模型是如何工作的,將有助你開拓你的編程視野。

加vx;tanzzhouyiwan 免費領取Python學習資料一套哦!


?


---------------------
作者:sxyyu1
來源:CSDN
原文:https://blog.csdn.net/sxyyu1/article/details/82841410
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

總結

以上是生活随笔為你收集整理的Python字节码介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。