精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

PyCodeObject 拾遺

開發 前端
虛擬機會根據不同的指令執行不同的邏輯,說白了 Python 虛擬機執行字節碼的邏輯就是把自己想象成一顆 CPU,并內置了一個巨型的 switch case 語句,其中每個指令都對應一個 case 分支。?

內置函數 compile

之前通過函數的 __code__ 屬性獲取了該函數的 PyCodeObject 對象,但是還有沒有其它的方法呢?顯然是有的,答案是通過內置函數 compile,不過在介紹 compile 之前,先介紹一下 eval 和 exec。

eval:傳入一個字符串,然后把字符串里面的內容當做表達式

a = 1
# 所以 eval("a") 就等價于 a
print(eval("a"))  # 1
print(eval("1 + 1 + 1"))  # 3

注意:eval 是有返回值的,返回值就是字符串里面的內容。所以 eval 接收的字符串里面一定是一個表達式,表達式計算之后是一個具體的值,比如 a = eval("1 + 2"),等價于 a = 3。

但如果是語句的話,比如 a = eval("b = 3"),這樣等價于 a = (b = 3),顯然這會出現語法錯誤。因此 eval 函數把字符串兩邊的引號剝掉之后,得到的一定是一個普通的值。

try:
    print(eval("xxx"))
except NameError as e:
    print(e)  # name 'xxx' is not defined

此時等價于 print(xxx),但是 xxx 沒有定義,所以報錯。

# 此時是合法的,等價于 print('xxx')
print(eval("'xxx'"))  # xxx

以上就是 eval 函數,使用起來還是很方便的。

exec:傳入一個字符串,把字符串里面的內容當成語句來執行,這個是沒有返回值的,或者說返回值是 None。

# 相當于 a = 1
exec("a = 1")  
print(a)  # 1

statement = """
a = 123
if a == 123:
    print("a 等于 123")
else:
    print("a 不等于 123")
"""
exec(statement)  # a 等于 123

注意:a 等于 123 并不是 exec 返回的,而是把上面那坨字符串當成普通代碼執行的時候 print 出來的。這便是 exec 的作用,將字符串當成語句來執行。

所以使用 exec 可以非常方便地創建多個變量。

import random

for i in range(1, 5):
    exec(f"a{i} = {random.randint(1, 100)}")

print(a1)  # 72
print(a2)  # 21
print(a3)  # 38
print(a4)  # 32

那么 exec 和 eval 的區別就顯而易見了,eval 是要求字符串里面的內容能夠當成一個值,并且該值就是 eval 函數的返回值。而 exec 則是直接執行里面的內容,返回值是 None。

print(eval("1 + 1"))  # 2
print(exec("1 + 1"))  # None

# 相當于 a = 2
exec("a = 1 + 1")
print(a)  # 2

try:
    # 相當于 a = 2,但很明顯 a = 2 是一個語句
    # 它無法作為一個值,因此放到 eval 里面就報錯了
    eval("a = 1 + 1")
except SyntaxError as e:
    print(e)  # invalid syntax (<string>, line 1)

還是很好區分的,但是 eval 和 exec 在生產中盡量要少用。另外,eval 和 exec 還可以接收第二個參數和第三個參數,我們在介紹名字空間的時候再說。

compile:關鍵來了,它執行后返回的就是一個 PyCodeObject 對象。

這個函數接收哪些參數呢?

  • 參數一:當成代碼執行的字符串
  • 參數二:可以為這些代碼起一個文件名
  • 參數三:執行方式,支持三種,分別是 exec、single、eval

我們演示一下。

# exec:將源代碼當做一個模塊來編譯
# single:用于編譯一個單獨的 Python 語句(交互式)
# eval:用于編譯一個 eval 表達式
statement = "a, b = 1, 2"
# 這里我們選擇 exec,當成一個模塊來編譯
co = compile(statement, "古明地覺的編程教室", "exec")

print(co.co_firstlineno)  # 1
print(co.co_filename)  # 古明地覺的編程教室
print(co.co_argcount)  # 0
# 我們是以 a, b = 1, 2 這種方式賦值
# 所以 (1, 2) 會被當成一個元組加載進來
# 從這里我們看到,元組是在編譯階段就已經確定好了
print(co.co_consts)  # ((1, 2), None)

statement = """
a = 1
b = 2
"""
co = compile(statement, "<file>", "exec")
print(co.co_consts)  # (1, 2, None)
print(co.co_names)  # ('a', 'b')

我們后面在分析 PyCodeObject 的時候,會經常使用 compile 函數。

然后 compile 還可以接收一個 flags 參數,也就是第四個參數,它的默認值為 0,表示按照標準模式進行編譯,就是之前說的那幾步。

  • 對文本形式的源代碼進行分詞,將其切分成一個個的 Token;
  • 對 Token 進行語法解析,生成抽象語法樹(AST);
  • 將 AST 編譯成 PyCodeObject 對象,簡稱 code 對象或者代碼對象;

但如果將 flags 指定為 1024,那么 compile 函數在生成 AST 之后會直接停止,然后返回一個 ast.Module 對象。

print(
    compile("a = 1", "<file>", "exec").__class__
)  # <class 'code'>

print(
    compile("a = 1", "<file>", "exec", flags=1024).__class__
)  # <class 'ast.Module'>

ast 模塊是和 Python 的抽象語法樹相關的,那么問題來了,這個 ast.Module 對象能夠干什么呢?別著急,我們后續在介紹棧幀的時候說。不過由于抽象語法樹比較底層,因此知道 compile 的前三個參數的用法即可。

字節碼與反編譯

關于 Python 的字節碼,是后面剖析虛擬機的重點,現在先來看一下。我們知道執行源代碼之前會先編譯得到 PyCodeObject 對象,里面的 co_code 字段指向了字節碼序列,或者說字節碼指令集。

虛擬機會根據這些指令集來進行一系列的操作(當然也依賴其它的靜態信息),從而完成對程序的執行。關于指令,解釋器定義了 200 多種,我們大致看一下。

// Include/opcode.h
#define CACHE                                    0
#define POP_TOP                                  1
#define PUSH_NULL                                2
#define INTERPRETER_EXIT                         3
#define END_FOR                                  4
#define END_SEND                                 5
#define NOP                                      9
#define UNARY_NEGATIVE                          11
#define UNARY_NOT                               12
#define UNARY_INVERT                            15
#define RESERVED                                17
#define BINARY_SUBSCR                           25
#define BINARY_SLICE                            26
#define STORE_SLICE                             27
#define GET_LEN                                 30
#define MATCH_MAPPING                           31
#define MATCH_SEQUENCE                          32
#define MATCH_KEYS                              33
#define PUSH_EXC_INFO                           35
#define CHECK_EXC_MATCH                         36
#define CHECK_EG_MATCH                          37
#define WITH_EXCEPT_START                       49
#define GET_AITER                               50
#define GET_ANEXT                               51
#define BEFORE_ASYNC_WITH                       52
#define BEFORE_WITH                             53
#define END_ASYNC_FOR                           54
#define CLEANUP_THROW                           55
#define STORE_SUBSCR                            60
#define DELETE_SUBSCR                           61
#define GET_ITER                                68
#define GET_YIELD_FROM_ITER                     69
#define LOAD_BUILD_CLASS                        71
#define LOAD_ASSERTION_ERROR                    74
#define RETURN_GENERATOR                        75
#define RETURN_VALUE                            83
// ...
// ...

所謂字節碼指令其實就是個整數,多個指令組合在一起便是字節碼指令集(字節碼序列),它是一個 bytes 對象。當然啦,指令集里面不全是指令,索引(偏移量)為偶數的字節表示指令,索引為奇數的字節表示指令參數,后續會細說。

然后我們可以通過反編譯的方式查看每行 Python 代碼都對應哪些操作指令。

# Python 的 dis 模塊專門負責干這件事情
import dis

def foo(a, b):
    c = a + b
    return c

# 里面接收 PyCodeObject 對象
# 當然函數也是可以的,會自動獲取 co_code
dis.dis(foo)
"""
  1           0 RESUME                   0

  2           2 LOAD_FAST                0 (a)
              4 LOAD_FAST                1 (b)
              6 BINARY_OP                0 (+)
             10 STORE_FAST               2 (c)

  3          12 LOAD_FAST                2 (c)
             14 RETURN_VALUE
"""

字節碼反編譯后的結果多么像匯編語言,其中第一列是源代碼行號,第二列是字節碼偏移量,第三列是字節碼指令(也叫操作碼),第四列是指令參數(也叫操作數)。Python 的字節碼指令都是成對出現的,每個指令會帶有一個指令參數。

查看字節碼也可以使用 opcode 模塊:

from opcode import opmap

opmap = {v: k for k, v in opmap.items()}

def foo(a, b):
    c = a + b
    return c

code = foo.__code__.co_code
for i in range(0, len(code), 2):
    print("操作碼: {:<12} 操作數: {}".format(
        opmap[code[i]], code[i+1]
    ))
"""
操作碼: RESUME       操作數: 0
操作碼: LOAD_FAST    操作數: 0
操作碼: LOAD_FAST    操作數: 1
操作碼: BINARY_OP    操作數: 0
操作碼: CACHE        操作數: 0
操作碼: STORE_FAST   操作數: 2
操作碼: LOAD_FAST    操作數: 2
操作碼: RETURN_VALUE 操作數: 0
"""

總之字節碼就是一段字節序列,轉成列表之后就是一堆數字。偶數位置表示指令本身,而每個指令后面都會跟一個指令參數,也就是奇數位置表示指令參數。

所以指令本質上只是一個整數:

圖片圖片

虛擬機會根據不同的指令執行不同的邏輯,說白了 Python 虛擬機執行字節碼的邏輯就是把自己想象成一顆 CPU,并內置了一個巨型的 switch case 語句,其中每個指令都對應一個 case 分支。

然后遍歷整條字節碼,拿到每一個指令和指令參數。接著對指令進行判斷,不同的指令進入不同的 case 分支,執行不同的處理邏輯,直到字節碼全部執行完畢或者程序出錯。

關于執行字節碼的具體流程,等介紹棧幀的時候細說。

責任編輯:武曉燕 來源: 古明地覺的編程教室
相關推薦

2022-10-12 23:39:46

Java接口屬性

2022-10-11 09:33:04

Java異常Exception

2018-11-30 15:17:38

CPUCache緩存行

2010-03-30 08:36:26

Java框架StrutsSpring

2021-03-19 16:05:33

CSS CSS 屬性CSS 基礎

2021-12-14 07:40:07

C# 異步流結合體

2021-06-25 10:18:08

JavaScript Array.map 巧技拾遺

2021-11-23 20:41:05

對象軟件設計

2024-09-30 16:08:43

Python虛擬機棧幀

2010-10-11 13:03:00

Windows Pho

2014-01-09 11:28:21

Windows 9

2009-07-07 08:33:51

微軟Windows 7操作系統

2016-07-29 10:37:00

互聯網httphtml

2024-11-15 16:27:58

函數結構存儲

2015-03-11 16:52:55

華為華為渠道

2016-11-04 14:44:37

華為拾貝

2011-07-08 15:22:29

英特爾云計算

2011-12-26 15:59:49

4GLTE無線基礎

2012-07-11 13:54:42

網頁重構

2022-04-18 10:13:54

元宇宙區塊鏈百悟科技
點贊
收藏

51CTO技術棧公眾號

婷婷四房综合激情五月| 日韩免费观看网站| 亚洲色图欧美日韩| 欧美另类老肥妇| 国产欧美日韩亚州综合| 91九色视频导航| 久久久久成人片免费观看蜜芽| 精品在线网站观看| 欧美日韩一区二区三区高清| 国产日韩欧美大片| 激情小说 在线视频| 国内精品久久久久影院薰衣草| 欧美黄色性视频| 成人免费无遮挡无码黄漫视频| 色综合.com| 天天免费综合色| 中文字幕中文字幕99 | 色帝国亚洲欧美在线| 91视频91自| 92裸体在线视频网站| 日本免费在线观看视频| 一区二区三区四区日韩| 亚洲欧美另类人妖| 国偷自产av一区二区三区麻豆| 欧美日韩一区在线播放| 中文文字幕文字幕高清| 黄色成人小视频| 狠狠躁夜夜躁人人躁婷婷91| 永久免费看av| 99精品老司机免费视频| 91一区二区三区在线观看| 亚洲www永久成人夜色| 免费黄色一级大片| 国产精品五区| 久久久女人电视剧免费播放下载| 奇米网一区二区| 亚洲精品小区久久久久久| 日韩女优av电影| 亚洲图色中文字幕| 欧美国产日韩电影| 91久久精品网| 黑森林福利视频导航| 欧美人与性动交α欧美精品济南到 | 久热精品视频在线观看一区| 无码人妻aⅴ一区二区三区69岛| 成人午夜大片| 欧美刺激脚交jootjob| 国产福利在线免费| 成人黄色图片网站| 在线亚洲欧美专区二区| 国产xxxxx在线观看| 国产激情视频在线看| 亚洲国产精品精华液网站| 女女百合国产免费网站| 韩国中文字幕在线| 中文字幕在线观看不卡视频| 亚洲一区二区免费视频软件合集| 国产女人在线视频| 国产午夜三级一区二区三| 久久久久久国产精品mv| 少妇荡乳情欲办公室456视频| 久久精品国产999大香线蕉| 国产精品嫩草影院久久久| 亚洲av无码不卡| 久久免费高清| 国产精品高清免费在线观看| www.久久视频| 免费不卡在线观看| 国产综合视频在线观看| 国产又粗又猛又爽| 精品一区二区三区免费毛片爱| 国产日韩欧美日韩大片| 国产女人高潮毛片| 国产69精品一区二区亚洲孕妇| 91九色对白| 欧美一级淫片aaaaaa| 99久久精品国产精品久久| 久久资源亚洲| eeuss影院在线播放| 亚洲欧美影音先锋| 干日本少妇视频| 国产黄色大片在线观看| 狠狠久久五月精品中文字幕| 日本一极黄色片| 欧美91在线|欧美| 欧美性一级生活| 午夜国产福利在线观看| 国产精品115| 亚洲男人天堂视频| 国产亚洲精品久久久久久豆腐| 五月久久久综合一区二区小说| 精品中文字幕乱| 国产精品黄色大片| 麻豆精品精品国产自在97香蕉| 亚洲r级在线观看| 欧美自拍偷拍一区二区| 国产亚洲欧美日韩在线一区| 91免费视频黄| 超碰在线资源| 欧美日韩一区高清| 午夜剧场免费看| 欧美色爱综合| 欧美国产日韩精品| 亚洲午夜无码久久久久| 国产成人午夜精品5599| 色就是色欧美| 2021中文字幕在线| 欧美日韩aaaaa| 污污污www精品国产网站| 日韩免费久久| 97香蕉久久超级碰碰高清版| 亚洲网站免费观看| 99re这里只有精品视频首页| 在线国产伦理一区| 樱花草涩涩www在线播放| 欧美妇女性影城| 9.1成人看片免费版| 欧美精品自拍| 国产精品网红福利| 日韩资源在线| 亚洲在线视频网站| 69久久久久久| 综合国产视频| 午夜精品福利电影| 亚洲AV无码国产精品午夜字幕 | 免费一区二区三区| 欧美日韩在线视频免费观看| 欧美日韩国产高清一区二区 | 欧美国产精品一区二区| 欧美激情视频免费看| 亚洲精品无播放器在线播放| 亚洲欧美另类国产| 国产成人亚洲欧洲在线| 国产91丝袜在线18| 亚洲小说欧美另类激情| 2019年精品视频自拍| 日韩成人高清在线| 久久久久久蜜桃| 国产美女视频一区| 老司机av福利| 日本午夜精品久久久久| 永久免费精品影视网站| 在线永久看片免费的视频| 337p粉嫩大胆噜噜噜噜噜91av| a级免费在线观看| 欧美日韩午夜电影网| 日韩视频在线免费| 一级aaaa毛片| 国产精品电影院| xxww在线观看| 人人狠狠综合久久亚洲婷婷| 国产成人一区二区三区电影| 欧美美乳在线| 色哟哟一区二区| 欧美老熟妇乱大交xxxxx| 亚洲一区欧美二区| 蜜桃av色综合| 小黄鸭精品aⅴ导航网站入口| 日韩精品www| 国产一级18片视频| 久久天堂av综合合色蜜桃网| 欧美a在线视频| 在线日韩一区| 国产mv免费观看入口亚洲| 麻豆导航在线观看| 91黄色免费看| 蜜桃av免费观看| 韩国理伦片一区二区三区在线播放 | 自拍偷拍欧美激情| 原创真实夫妻啪啪av| 欧美日韩天堂| 精品999在线观看| 中文字幕在线直播| 一二美女精品欧洲| 国产美女永久免费| 亚洲午夜久久久久中文字幕久| 久久免费精品国产| 久久亚洲风情| 亚洲一区三区视频在线观看| 麻豆久久一区| 97超级碰碰人国产在线观看| 国产在线超碰| 911精品产国品一二三产区| 久久一二三四区| 2020国产精品自拍| 久久国产激情视频| 亚洲精品欧洲| 亚洲国产午夜伦理片大全在线观看网站 | 亚欧在线免费观看| 亚洲欧美综合久久久| 国产精品xxxx| 国精产品一区一区三区四川| 久久精品视频一| 高h放荡受浪受bl| 一本一本大道香蕉久在线精品| 国产一级淫片久久久片a级| 国产精品综合网| 欧美精品久久久久久久免费| 欧美精品系列| 国产精品一区二区在线观看| 国产超碰精品| 欧美尺度大的性做爰视频| 日韩a在线观看| 91麻豆精品国产91久久久 | www.久久国产| 久久成人精品无人区| 国产在线播放观看| 欧美电影免费观看高清| 狠狠干一区二区| 四虎视频在线精品免费网址| **欧美日韩vr在线| a毛片在线看免费观看| 亚洲天堂成人在线| 蜜臀久久99精品久久久| 欧美在线播放高清精品| 懂色av.com| 亚洲色图丝袜美腿| 欧美 日韩 成人| 成人动漫精品一区二区| 亚洲日本黄色片| 巨乳诱惑日韩免费av| 国产天堂视频在线观看| 性欧美69xoxoxoxo| 视频在线99re| 竹菊久久久久久久| 激情视频一区二区| 亚洲无线观看| 成人国产在线视频| 国产精品亚洲d| 欧美与黑人午夜性猛交久久久| 污视频网站在线免费| 日韩视频在线免费观看| 久草在线青青草| 日韩国产一区三区| 天天摸夜夜添狠狠添婷婷| 日韩亚洲欧美在线| 国产乱色精品成人免费视频| 欧美视频一区二区| 日韩黄色片网站| 精品国产乱码久久久久酒店| 久久婷婷一区二区| 一区二区三区四区视频精品免费| 手机在线中文字幕| 中文一区二区完整视频在线观看| 自拍偷拍中文字幕| 久久亚洲精品小早川怜子| 一本加勒比波多野结衣| 成人精品在线视频观看| zjzjzjzjzj亚洲女人| 国产99久久久国产精品潘金| 国产精品中文久久久久久| 紧缚捆绑精品一区二区| 中文字幕第一页在线视频| 美女mm1313爽爽久久久蜜臀| 久久久精品三级| 奇米影视7777精品一区二区| 奇米影视四色在线| 久久精品久久久精品美女| 欧美美女性视频| 国产精品亚洲一区二区三区在线| 久久精品一卡二卡| 国产电影精品久久禁18| 亚洲国产精品第一页| 成人高清伦理免费影院在线观看| 日本一区二区免费视频| 成人精品电影在线观看| 中文字幕在线永久| 2020国产精品自拍| 美国美女黄色片| 国产精品系列在线| 久久久久久久久久久久久女过产乱| 一区二区在线电影| 懂色av.com| 在线免费不卡视频| 91在线视频国产| 欧美成人一区二区三区| 无码国精品一区二区免费蜜桃| 亚洲人在线观看| 久久综合网导航| 久久久久久久爱| 日韩电影大全网站| 91精品久久久久久综合乱菊 | 国产精品69久久久久孕妇欧美| 亚洲视频免费观看| 久久免费激情视频| 欧美日韩电影一区| 国 产 黄 色 大 片| 亚洲人成亚洲人成在线观看| 欧美日韩在线资源| 久久理论片午夜琪琪电影网| a毛片不卡免费看片| 国产精品久久久久久久久久新婚| 经典三级久久| 久久精品国产综合精品 | www.日本三级| 久久久999| 国产毛片久久久久久| 91日韩一区二区三区| 成人高潮免费视频| 色综合久久久久综合99| av网站免费大全| 亚洲品质视频自拍网| 中文字幕有码在线视频| 国产成人在线亚洲欧美| 亚洲综合网狠久久| 亚洲欧洲另类精品久久综合| 国产精品www.| 久久国产激情视频| 久久综合久久鬼色| 麻豆精品一区二区三区视频| 欧美最新大片在线看| 免费看日韩av| 久久久www成人免费精品张筱雨| 免费成人在线电影| 亚洲综合在线播放| 精品久久久久久久久久久aⅴ| 国产玉足脚交久久欧美| 久久精品国产一区二区三区免费看| 成熟妇人a片免费看网站| 亚洲欧美在线另类| 日本成人一级片| 日韩精品在线观看一区| 欧美78videosex性欧美| 91嫩草在线视频| 欧美性感美女一区二区| 国产h视频在线播放| 国产河南妇女毛片精品久久久| 1024手机在线观看你懂的| 天天影视网天天综合色在线播放| 午夜老司机福利| 日韩视频在线观看免费| 国产成人午夜性a一级毛片| 久久香蕉综合色| 亚洲少妇自拍| 亚洲av熟女高潮一区二区| 亚洲激情中文1区| 国产农村妇女毛片精品久久| 日韩在线播放视频| 福利一区和二区| 日韩欧美亚洲在线| 日韩一区欧美二区| 亚洲AV无码国产成人久久| 欧美午夜精品在线| 婷婷在线免费观看| 97视频在线看| 秋霞影视一区二区三区| 激情深爱综合网| 99精品欧美一区二区三区综合在线| 国产污片在线观看| 精品日韩成人av| 丁香花高清在线观看完整版| 成人在线观看av| 欧美三级乱码| 老司机午夜免费福利| 亚洲国产综合色| 午夜一区在线观看| 清纯唯美亚洲激情| 欧州一区二区| 午夜久久福利视频| 亚洲日本在线视频观看| 国产高清免费观看| 欧美激情中文网| 欧美电影免费网站| 国产激情在线观看视频| 欧美韩日一区二区三区| 伊人久久国产精品| 欧美成人精品在线观看| 国产精品巨作av| 逼特逼视频在线| 国产欧美综合在线| 国产精品欧美亚洲| 久久久噜噜噜久久久| 亚洲国产精品嫩草影院久久av| 性欧美极品xxxx欧美一区二区| 国产精品乱码人人做人人爱| 国产欧美日韩成人| 久久的精品视频| 久久香蕉精品香蕉| 五月婷婷丁香综合网| 亚洲欧美日韩精品久久久久| 特黄aaaaaaaaa真人毛片| 日本视频久久久| 小处雏高清一区二区三区| 国产精品久久久久久在线观看| 一本一本大道香蕉久在线精品| 1769视频在线播放免费观看| http;//www.99re视频| 天堂精品中文字幕在线| 中文字幕av播放| 日韩成人网免费视频| 欧美一区=区三区| 免费拍拍拍网站| 国产农村妇女毛片精品久久麻豆| 国产伦一区二区| 55夜色66夜色国产精品视频| 区一区二视频| 亚洲熟女乱综合一区二区三区| 欧美日韩一区高清| 国产一二在线播放| 亚洲免费视频播放|