ã¿ãªããããã«ã¡ã¯ïŒ æ¥ãæ¥ãŸãããããã¯
ãPythonéçºè
ã³ãŒã¹ã®éå§åã«1ãææªæºãæ®ã£ãŠããããšãæå³ããŸãã ç§ãã¡ã®ä»æ¥ã®åºçç©ããã®ã³ãŒã¹ã«æ§ããããŸãã

ã¿ã¹ã¯ïŒ-Pythonã®å
éšæ§é ã«ã€ããŠåŠã³ãŸãã
-æœè±¡æ§ææšïŒASTïŒãæ§ç¯ããååãçè§£ããŸãã
-æéãšã¡ã¢ãªã«ããå¹ççãªã³ãŒããèšè¿°ããŸãã
äºåçãªæšå¥šäºé
ïŒ-éèš³è
ã®ä»äºã®åºæ¬çãªçè§£ïŒASTãããŒã¯ã³ãªã©ïŒã
-Pythonã®ç¥èã
-Cã®åºç€ç¥è
batuhan@arch-pc î° ~/blogs/cpython/exec_model î° python --version Python 3.7.0
CPythonå®è¡ã¢ãã«Pythonã¯ãã³ã³ãã€ã«ããè§£éãããèšèªã§ãã ãããã£ãŠãPythonã³ã³ãã€ã©ã¯ãã€ãã³ãŒããçæããã€ã³ã¿ãŒããªã¿ãŒãããããå®è¡ããŸãã ãã®èšäºã§ã¯ã次ã®åé¡ã«ã€ããŠæ€èšããŸãã
- è§£æãšããŒã¯ã³åïŒ
- ASTã®å€æã
- å¶åŸ¡ãããŒã°ã©ãïŒCFGïŒ;
- ãã€ãã³ãŒã
- CPythonä»®æ³ãã·ã³ã§å®è¡ããŸãã
è§£æãšããŒã¯ã³åã
ææ³ãææ³ã¯ãPythonèšèªã®ã»ãã³ãã£ã¯ã¹ãå®çŸ©ããŸãã ãŸããããŒãµãŒãèšèªãè§£éããæ¹æ³ã瀺ãã®ã«ã圹ç«ã¡ãŸãã Pythonã®ææ³ã§ã¯ãæ¡åŒµããã«ã¹ããŠã¢åœ¢åŒã«äŒŒãæ§æã䜿çšããŸãã ãœãŒã¹èšèªã®ç¿»èš³è
çšã®ç¬èªã®ææ³ããããŸãã ææ³ãã¡ã€ã«ã¯ãcpython / Grammar / Grammarããã£ã¬ã¯ããªã«ãããŸãã
以äžã¯ææ³ã®äŸã§ãã
batuhan@arch-pc î° ~/cpython/Grammar î° î master î° grep "simple_stmt" Grammar | head -n3 | tail -n1 simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
åçŽãªåŒã«ã¯å°ããªåŒãšè§ãã£ããå«ãŸããã³ãã³ãã¯æ°ããè¡ã§çµäºããŸãã å°ããªåŒã¯ãã€ã³ããŒãããåŒã®ãªã¹ãã®ããã«èŠããŸã...
ä»ã®ããã€ãã®è¡šçŸ:)
small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt) ... del_stmt: 'del' exprlist pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue'
ããŒã¯ã³åïŒLexingïŒããŒã¯ã³åã¯ãããã¹ãããŒã¿ã¹ããªãŒã ãååŸãã远å ã®ã¡ã¿ããŒã¿ã䜿çšããŠéèŠãªïŒã€ã³ã¿ãŒããªã¿ãŒçšïŒåèªã®ããŒã¯ã³ã«åå²ããããã»ã¹ã§ãïŒããšãã°ãããŒã¯ã³ã®éå§äœçœ®ãšçµäºäœçœ®ããã®ããŒã¯ã³ã®æååå€ãªã©ïŒã
ããŒã¯ã³ããŒã¯ã³ã¯ããã¹ãŠã®ããŒã¯ã³ã®å®çŸ©ãå«ãããããŒãã¡ã€ã«ã§ãã Pythonã«ã¯59çš®é¡ã®ããŒã¯ã³ïŒInclude / token.hïŒããããŸãã
以äžã¯ãã®äžéšã®äŸã§ãã
ããã€ãã®Pythonã³ãŒããããŒã¯ã³ã«åå²ãããšè¡šç€ºãããŸãã
CLIã«ããããŒã¯ã³åãããtests.pyãã¡ã€ã«ã§ã
def greetings(name: str): print(f"Hello {name}") greetings("Batuhan")
次ã«ãpython -m tokenizeã³ãã³ãã䜿çšããŠããŒã¯ã³åããæ¬¡ã®ããã«åºåããŸãã
batuhan@arch-pc î° ~/blogs/cpython/exec_model î° python -m tokenize tests.py 0,0-0,0: ENCODING 'utf-8' ... 2,0-2,4: INDENT ' ' 2,4-2,9: NAME 'print' ... 4,0-4,0: DEDENT '' ... 5,0-5,0: ENDMARKER ''
ããã§ãæ°åïŒããšãã°ã1.4-1.13ïŒã¯ãããŒã¯ã³ã®éå§äœçœ®ãšçµäºäœçœ®ã瀺ããŸãã ãšã³ã³ãŒãããŒã¯ã³ã¯ãåžžã«æåã«åãåãããŒã¯ã³ã§ãã ãœãŒã¹ãã¡ã€ã«ã®ãšã³ã³ãŒãã«é¢ããæ
å ±ãæäŸããåé¡ãããå Žåãã€ã³ã¿ãŒããªã¿ãŒã¯äŸå€ãã¹ããŒããŸãã
tokenize.tokenizeã«ããããŒã¯ã³åã³ãŒããããã¡ã€ã«ãããŒã¯ã³åããå¿
èŠãããå Žåã¯ã
stdlibã® tokenizeã¢ãžã¥ãŒã«ã䜿çšã§ããŸãã
>>> with open('tests.py', 'rb') as f: ... for token in tokenize.tokenize(f.readline): ... print(token) ... TokenInfo(type=57 (ENCODING), string='utf-8', start=(0, 0), end=(0, 0), line='') ... TokenInfo(type=1 (NAME), string='greetings', start=(1, 4), end=(1, 13), line='def greetings(name: str):\n') ... TokenInfo(type=53 (OP), string=':', start=(1, 24), end=(1, 25), line='def greetings(name: str):\n') ...
ããŒã¯ã³ã®ã¿ã€ãã¯ã
token.hããããŒãã¡ã€ã«ã®IDã§ã
ã æååã¯ããŒã¯ã³ã®å€ã§ãã éå§ãšçµäºã¯ãããããããŒã¯ã³ã®éå§äœçœ®ãšçµäºäœçœ®ã瀺ããŸãã
ä»ã®èšèªã§ã¯ããããã¯ã¯æ¬åŒ§ãŸãã¯éå§/çµäºã¹ããŒãã¡ã³ãã§ç€ºãããŸãããPythonã¯ã€ã³ãã³ããšç°ãªãã¬ãã«ã䜿çšããŸãã INDENTããã³DEDENTããŒã¯ã³ãšã€ã³ãã³ãã瀺ããŸãã ãããã®ããŒã¯ã³ã¯ããªã¬ãŒã·ã§ãã«è§£æããªãŒããã³/ãŸãã¯æœè±¡æ§æããªãŒãæ§ç¯ããããã«å¿
èŠã§ãã
ããŒãµãŒã®çæããŒãµãŒçæ-æå®ã®ææ³ã«åŸã£ãŠããŒãµãŒãçæããããã»ã¹ã ããŒãµãŒãžã§ãã¬ãŒã¿ãŒã¯PGenãšããŠç¥ãããŠããŸãã Cpythonã«ã¯2ã€ã®ããŒãµãŒãžã§ãã¬ãŒã¿ãŒããããŸãã 1ã€ã¯ãªãªãžãã«ïŒ
Parser/pgen
ïŒã§ããã1ã€ã¯PythonïŒ
/Lib/lib2to3/pgen2
ïŒã§æžãçŽãããŠããŸãã
ãå
ã®ãžã§ãã¬ãŒã¿ã¯ãç§ãPythonåãã«æžããæåã®ã³ãŒãã§ããã
-ã¬ã€ãäžèšã®åŒçšããã
pgenã¯ããã°ã©ãã³ã°èšèªã§æãéèŠãªãã®ã§ããããšãæããã«ãªããŸãã ïŒ
Parser / pgenã§ ïŒpgenãåŒã³åºããšãããããŒãã¡ã€ã«ãšCãã¡ã€ã«ïŒããŒãµãŒèªäœïŒãçæãããŸãã çæãããCã³ãŒããèŠããšãæå³ã®ããå€èгã¯ãªãã·ã§ã³ã§ãããããç¡æå³ã«èŠãããããããŸããã 倿°ã®éçããŒã¿ãšæ§é ãå«ãŸããŠããŸãã ããã«ããã®äž»ãªã³ã³ããŒãã³ãã説æããããšããŸãã
DFAïŒå®çŸ©æžã¿ã¹ããŒããã·ã³ïŒããŒãµãŒã¯ãé端æ«ããšã«1ã€ã®DFAãå®çŸ©ããŸãã åDFAã¯ãç¶æ
ã®é
åãšããŠå®çŸ©ãããŸãã
static dfa dfas[87] = { {256, "single_input", 0, 3, states_0, "\004\050\340\000\002\000\000\000\012\076\011\007\262\004\020\002\000\300\220\050\037\202\000"}, ... {342, "yield_arg", 0, 3, states_86, "\000\040\200\000\002\000\000\000\000\040\010\000\000\000\020\002\000\300\220\050\037\000\000"}, };
åDFAã«ã¯ãç¹å¥ãªéã¿ãŒããã«ãã©ã®ããŒã¯ã³ã§éå§ã§ãããã瀺ãã¹ã¿ãŒã¿ãŒãããããããŸãã
ç¶æ
åç¶æ
ã¯ãé·ç§»/ãšããžïŒã¢ãŒã¯ïŒã®é
åã«ãã£ãŠå®çŸ©ãããŸãã
static state states_86[3] = { {2, arcs_86_0}, {1, arcs_86_1}, {1, arcs_86_2}, };
é·ç§»ïŒã¢ãŒã¯ïŒåé·ç§»é
åã«ã¯2ã€ã®çªå·ããããŸãã æåã®çªå·ã¯é·ç§»ã®ååïŒã¢ãŒã¯ã©ãã«ïŒã§ãã·ã³ãã«çªå·ãæããŸãã 2çªç®ã®çªå·ã¯å®å
ã§ãã
static arc arcs_86_0[2] = { {77, 1}, {47, 2}, }; static arc arcs_86_1[1] = { {26, 2}, }; static arc arcs_86_2[1] = { {0, 2}, };
ååïŒã©ãã«ïŒããã¯ãã·ã³ãã«ã®IDãé·ç§»ã®ååã«ãããããç¹å¥ãªããŒãã«ã§ãã
static label labels[177] = { {0, "EMPTY"}, {256, 0}, {4, 0}, ... {1, "async"}, {1, "def"}, ... {1, "yield"}, {342, 0}, };
çªå·1ã¯ãã¹ãŠã®èå¥åã«å¯Ÿå¿ããŸãã ãããã£ãŠããããããã¹ãŠåãæåIDãæã£ãŠããå Žåã§ãããããããç°ãªãé·ç§»åãååŸããŸãã
ç°¡åãªäŸïŒ1-trueã®å ŽåããHiããåºåããã³ãŒãããããšããŸãã
if 1: print('Hi')
ããŒãµãŒã¯ãã®ã³ãŒããsingle_inputãšèŠãªããŸãã
single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
次ã«ãè§£æããªãŒã¯ã1åéãã®å
¥åã®ã«ãŒãããŒãããå§ãŸããŸãã

ãããŠãDFAïŒsingle_inputïŒã®å€ã¯0ã§ãã
static dfa dfas[87] = { {256, "single_input", 0, 3, states_0, "\004\050\340\000\002\000\000\000\012\076\011\007\262\004\020\002\000\300\220\050\037\202\000"} ... }
次ã®ããã«ãªããŸãã
static arc arcs_0_0[3] = { {2, 1}, {3, 1}, {4, 2}, }; static arc arcs_0_1[1] = { {0, 1}, }; static arc arcs_0_2[1] = { {2, 1}, }; static state states_0[3] = { {3, arcs_0_0}, {1, arcs_0_1}, {1,
arcs_0_2}ã
};
ããã§ã
arc_0_0
ã¯3ã€ã®èŠçŽ ã§æ§æãããŠããŸãã æåã¯
NEWLINE
ã2çªç®ã¯
simple_stmt
ãæåŸã¯
compound_stmt
ã§ãã
simple_stmt
ã®åæã»ãããèãããšã
simple_stmt
ã¯
if
éå§ã§ããªããšçµè«ä»ããããšãã§ããŸãã ãã ãã
if
ãæ°ããè¡ã§ã¯ãªã
if
ã§ãã
compound_stmt
ã¯
if
éå§ã§ããŸãã ãããã£ãŠãæåŸã®
arc ({4;2})
ããè¡ã£ãŠã
compound_stmt
ããŒããè§£æããªãŒã«è¿œå ãã2çªç®ã«ç§»åããåã«æ°ããDFAã«åãæ¿ããŸãã æŽæ°ãããè§£æããªãŒãååŸããŸãã

æ°ããDFAã¯è€åã¹ããŒãã¡ã³ããè§£æããŸãã
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt
ãããŠã次ã®ãã®ãåŸãããŸãã
static arc arcs_39_0[9] = { {91, 1}, {92, 1}, {93, 1}, {94, 1}, {95, 1}, {19, 1}, {18, 1}, {17, 1}, {96, 1}, }; static arc arcs_39_1[1] = { {0, 1}, }; static state states_39[2] = { {9, arcs_39_0}, {1, arcs_39_1}, };
if
å§ãŸãã®ã¯æåã®ãžã£ã³ãã®ã¿
if
ã æŽæ°ãããè§£æããªãŒãååŸããŸãã

次ã«ãDFAãååºŠå€æŽããæ¬¡ã®DFAãifsãè§£æããŸãã
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
ãã®çµæãæå®97ã®é·ç§»ã®ã¿ãååŸãããŸããããã¯
if
ããŒã¯ã³ãšäžèŽããŸãã
static arc arcs_41_0[1] = { {97, 1}, }; static arc arcs_41_1[1] = { {26, 2}, }; static arc arcs_41_2[1] = { {27, 3}, }; static arc arcs_41_3[1] = { {28, 4}, }; static arc arcs_41_4[3] = { {98, 1}, {99, 5}, {0, 4}, }; static arc arcs_41_5[1] = { {27, 6}, }; static arc arcs_41_6[1] = { {28, 7}, }; ...
åãDFAã®ãŸãŸã§æ¬¡ã®ç¶æ
ã«åãæ¿ãããšã次ã®arcs_41_1ã«ã1ã€ã®é·ç§»ãããããŸããã ããã¯ãã¹ã端æ«ã«ãåœãŠã¯ãŸããŸãã æ°åïŒããšãã°ã1ïŒã§å§ãŸãå¿
èŠããããŸãã

ã³ãã³ããŒã¯ã³ïŒ:)ãåãåãarc_41_2ã«ã¯é·ç§»ã1ã€ãããããŸããã

ãããã£ãŠãå°å·å€ã§éå§ã§ããã»ãããååŸããŸãã æåŸã«ãarcs_41_4ã«ç§»åããŸãã ã»ããå
ã®æåã®é·ç§»ã¯elifåŒã§ããã2çªç®ã¯elseã§ããã3çªç®ã¯æåŸã®ç¶æ
ã§ãã ãããŠãè§£æããªãŒã®æçµãã¥ãŒãååŸããŸãã
ããŒãµãŒçšã®Pythonã€ã³ã¿ãŒãã§ã€ã¹ã
Pythonã§ã¯ãããŒãµãŒãšåŒã°ããã¢ãžã¥ãŒã«ã䜿çšããŠãåŒã®è§£æããªãŒãç·šéã§ããŸãã
>>> import parser >>> code = "if 1: print('Hi')"
parser.suiteã䜿çšããŠãç¹å®ã®æ§æããªãŒïŒConcrete Syntax TreeãCSTïŒãçæã§ããŸãã
>>> parser.suite(code).tolist() [257, [269, [295, [297, [1, 'if'], [305, [309, [310, [311, [312, [315, [316, [317, [318, [319, [320, [321, [322, [323, [324, [2, '1']]]]]]]]]]]]]]]], [11, ':'], [304, [270, [271, [272, [274, [305, [309, [310, [311, [312, [315, [316, [317, [318, [319, [320, [321, [322, [323, [324, [1, 'print']], [326, [7, '('], [334, [335, [305, [309, [310, [311, [312, [315, [316, [317, [318, [319, [320, [321, [322, [323, [324, [3, "'Hi'"]]]]]]]]]]]]]]]]]], [8, ')']]]]]]]]]]]]]]]]]]], [4, '']]]]]], [4, ''], [0, '']]
åºåå€ã¯ãã¹ãããããªã¹ãã«ãªããŸãã æ§é å
ã®åãªã¹ãã«ã¯2ã€ã®èŠçŽ ããããŸãã æåã¯æåã®IDïŒ0-256-端æ«ã256 +-é端æ«ïŒã§ã2çªç®ã¯ç«¯æ«ã®ããŒã¯ã³ã®æååã§ãã
æœè±¡æ§æããªãŒå®éãæœè±¡æ§æããªãŒïŒASTïŒã¯ãåé ç¹ãç°ãªãçš®é¡ã®èšèªæ§æèŠçŽ ïŒåŒã倿°ãæŒç®åãªã©ïŒã衚ãããªãŒåœ¢åŒã®ãœãŒã¹ã³ãŒãã®æ§é 衚çŸã§ãã
æšãšã¯äœã§ããïŒããªãŒã¯ãå§ç¹ãšããŠã«ãŒãé ç¹ãæã€ããŒã¿æ§é ã§ãã ã«ãŒãé ç¹ã¯ãåå²ïŒé·ç§»ïŒã«ãã£ãŠä»ã®é ç¹ãŸã§äžããããŸãã ã«ãŒããé€ãåé ç¹ã«ã¯ãäžæã®èŠªé ç¹ã1ã€ãããŸãã
æœè±¡æ§æããªãŒãšæ§æè§£æããªãŒã®éã«ã¯äžå®ã®éãããããŸãã

å³åŽã«ã¯ãåŒ2 * 7 + 3ã®è§£æããªãŒããããŸãã ããã¯æåéããããªãŒå
ã®ãœãŒã¹ã³ãŒãã®1察1ã®ã€ã¡ãŒãžã§ãã ãã¹ãŠã®åŒãçšèªãå€ã衚瀺ãããŸãã ãã ãããã®ãããªã€ã¡ãŒãžã¯åçŽãªã³ãŒãã§ã¯è€éããããããèšç®ã®ããã«ã³ãŒãã§å®çŸ©ããå¿
èŠããã£ããã¹ãŠã®æ§æè¡šçŸãåçŽã«åé€ã§ããŸãã
ãã®ãããªåçŽåãããããªãŒã¯ãæœè±¡æ§æããªãŒïŒASTïŒãšåŒã°ããŸãã å³ã®å·ŠåŽã«ã¯ãåãã³ãŒãã«å¯ŸããŠæ£ç¢ºã«ç€ºãããŠããŸãã ãã¹ãŠã®æ§æè¡šçŸã¯çè§£ã容æã«ããããã«ç Žæ£ãããŸããããç¹å®ã®æ
å ±ã倱ãããããšãèŠããŠãããŠãã ããã
äŸ
Pythonã¯ãASTãæäœããããã®çµã¿èŸŒã¿ASTã¢ãžã¥ãŒã«ãæäŸããŸãã ASTããªãŒããã³ãŒããçæããã«ã¯ã
Astorãªã©ã®ãµãŒãããŒãã£ã¢ãžã¥ãŒã«ã䜿çšã§ããŸãã
ããšãã°ã以åãšåãã³ãŒããèããŸãã
>>> import ast >>> code = "if 1: print('Hi')"
ASTãååŸããã«ã¯ãast.parseã¡ãœããã䜿çšããŸãã
>>> tree = ast.parse(code) >>> tree <_ast.Module object at 0x7f37651d76d8>
ast.dump
ã¡ãœããã䜿çšããŠãããèªã¿ãããæœè±¡æ§æããªãŒãååŸããŠãã ããã
>>> ast.dump(tree) "Module(body=[If(test=Num(n=1), body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Str(s='Hi')], keywords=[]))], orelse=[])])"
ASTã¯äžè¬ã«ãæ§æè§£æããªãŒãããèŠèŠçã§çè§£ãããããšèããããŠããŸãã
å¶åŸ¡ãããŒã°ã©ãïŒCFGïŒå¶åŸ¡ãããŒã°ã©ãã¯ãäžé衚çŸãå«ãããŒã¹ãããã¯ã䜿çšããŠããã°ã©ã ã®ãããŒãã¢ãã«åããæ¹åã°ã©ãã§ãã
éåžžãCFGã¯ã³ãŒãåºåå€ãååŸããåã®åã®æé ã§ãã ã³ãŒãã¯ãCFGã®åŸæ¹ããã®æ·±ãæ€çŽ¢ã䜿çšããŠãå
é ããé ã«ããŒã¹ãããã¯ããçŽæ¥çæãããŸãã
ãã€ãã³ãŒãPythonãã€ãã³ãŒãã¯ãPythonä»®æ³ãã·ã³ã§åäœããåœä»€ã®äžéã»ããã§ãã ãœãŒã¹ã³ãŒããå®è¡ãããšãPythonã¯__pycache__ãšãããã£ã¬ã¯ããªãäœæããŸãã ã³ã³ãã€ã«ãåéããå Žåã«æéãç¯çŽããããã«ãã³ã³ãã€ã«ãããã³ãŒããä¿åããŸãã
func.pyã®åçŽãªPython颿°ãèããŠãã ããã
def say_hello(name: str): print("Hello", name) print(f"How are you {name}?")
>>> from func import say_hello >>> say_hello("Batuhan") Hello Batuhan How are you Batuhan?
say_hello
ãªããžã§ã¯ã
say_hello
ã¯é¢æ°ã§ãã
>>> type(say_hello) <class 'function'>
__code__
屿§ããããŸãã
>>> say_hello.__code__ <code object say_hello at 0x7f13777d9150, file "/home/batuhan/blogs/cpython/exec_model/func.py", line 1>
ã³ãŒããªããžã§ã¯ãã³ãŒããªããžã§ã¯ãã¯ãã³ãŒãã®å®è¡ã«å¿
èŠãªåœä»€ãŸãã¯ã¡ã¿ããŒã¿ãå«ãäžå€ã®ããŒã¿æ§é ã§ãã ç°¡åã«èšãã°ããããã¯Pythonã³ãŒãã®è¡šçŸã§ãã
compileã¡ãœããã䜿çšããŠæœè±¡æ§æããªãŒãã³ã³ãã€ã«ããããšã«ãããã³ãŒããªããžã§ã¯ããååŸããããšãã§ããŸãã
>>> import ast >>> code = """ ... def say_hello(name: str): ... print("Hello", name) ... print(f"How are you {name}?") ... say_hello("Batuhan") ... """ >>> tree = ast.parse(code, mode='exec') >>> code = compile(tree, '<string>', mode='exec') >>> type(code) <class 'code'>
åã³ãŒããªããžã§ã¯ãã«ã¯ãç¹å®ã®æ
å ±ïŒco_ã§å§ãŸãïŒãå«ã屿§ããããŸãã ããã§ã¯ããã®ãã¡ã®ã»ãã®ããã€ãã«ã€ããŠèšåããŸãã
co_nameæå§ãã«ãååã 颿°ãååšããå Žåã¯ãããããååãä»ããå¿
èŠããããŸãããã®ååã¯é¢æ°ã®ååã«ãªããŸããã¯ã©ã¹ãšåæ§ã®ç¶æ³ã§ãã ASTã®äŸã§ã¯ãã¢ãžã¥ãŒã«ã䜿çšããã³ã³ãã€ã©ãŒã«ãããã®ååãæ£ç¢ºã«äŒããããšãã§ããŸãã ããããåãªã
module
ã
>>> code.co_name '<module>' >>> say_hello.__code__.co_name 'say_hello'
co_varnamesããã¯ãåŒæ°ãå«ããã¹ãŠã®ããŒã«ã«å€æ°ãå«ãã¿ãã«ã§ãã
>>> say_hello.__code__.co_varnames ('name',)
co_conts颿°ã®æ¬äœã§ã¢ã¯ã»ã¹ãããã¹ãŠã®ãªãã©ã«ãšå®æ°å€ãå«ãã¿ãã«ã å€Noneã«æ³šç®ãã䟡å€ããããŸãã 颿°ã®æ¬äœã«ã¯Noneãå«ããŸããã§ããããPythonã¯ããã瀺ããŸããã颿°ãå®è¡ãéå§ããæ»ãå€ãåãåããã«çµäºãããšãNoneãè¿ãããã§ãã
>>> say_hello.__code__.co_consts (None, 'Hello', 'How are you ', '?')
ãã€ãã³ãŒãïŒco_codeïŒä»¥äžã¯é¢æ°ã®ãã€ãã³ãŒãã§ãã
>>> bytecode = say_hello.__code__.co_code >>> bytecode b't\x00d\x01|\x00\x83\x02\x01\x00t\x00d\x02|\x00\x9b\x00d\x03\x9d\x03\x83\x01\x01\x00d\x00S\x00'
ããã¯æååã§ã¯ãªãããã€ããªããžã§ã¯ããã€ãŸããã€ãã®ã·ãŒã±ã³ã¹ã§ãã
>>> type(bytecode) <class 'bytes'>
å°å·ãããæåã®æåã¯ãtãã§ãã æ°å€ãæ±ãããšã次ã®ããã«ãªããŸãã
>>> ord('t') 116
116ã¯ãã€ãã³ãŒã[0]ãšåãã§ãã
>>> assert bytecode[0] == ord('t')
ç§ãã¡ã«ãšã£ãŠãå€116ã¯äœãæå³ããŸããã 幞ããªããšã«ãPythonã¯disïŒfrom disassemblyïŒãšããæšæºã©ã€ãã©ãªãæäŸããŠããŸãã opnameãªã¹ãã䜿çšããå Žåã«åœ¹ç«ã¡ãŸãã ããã¯ããã¹ãŠã®ãã€ãã³ãŒãåœä»€ã®ãªã¹ãã§ããåã€ã³ããã¯ã¹ã¯åœä»€ã®ååã§ãã
>>> dis.opname[ord('t')] 'LOAD_GLOBAL'
å¥ã®ããè€éãªé¢æ°ãäœæããŸãããã
>>> def multiple_it(a: int): ... if a % 2 == 0: ... return 0 ... return a * 2 ... >>> multiple_it(6) 0 >>> multiple_it(7) 14 >>> bytecode = multiple_it.__code__.co_code
ãããŠããã€ãã³ãŒãã®æåã®åœä»€ãèŠã€ããŸãã
>>> dis.opname[bytecode[0]] 'LOAD_FAST
LOAD_FASTã¹ããŒãã¡ã³ãã¯2ã€ã®èŠçŽ ã§æ§æãããŸãã
>>> dis.opname[bytecode[0]] + ' ' + dis.opname[bytecode[1]] 'LOAD_FAST <0>'
Loadfast 0åœä»€ã¯ãã¿ãã«å
ã®å€æ°åãæ€çŽ¢ãããŒãã€ã³ããã¯ã¹ãæã€èŠçŽ ãå®è¡ã¹ã¿ãã¯å
ã®ã¿ãã«ã«ããã·ã¥ããŸãã
>>> multiple_it.__code__.co_varnames[bytecode[1]] 'a'
ã³ãŒãã¯dis.disã䜿çšããŠéã¢ã»ã³ãã«ãããã€ãã³ãŒãã䜿ãæ
£ãã圢åŒã«å€æã§ããŸãã ããã§ãæ°åïŒ2,3,4ïŒã¯è¡çªå·ã§ãã Pythonã®åã³ãŒãè¡ã¯ãäžé£ã®åœä»€ãšããŠå±éãããŸãã
>>> dis.dis(multiple_it) 2 0 LOAD_FAST 0 (a) 2 LOAD_CONST 1 (2) 4 BINARY_MODULO 6 LOAD_CONST 2 (0) 8 COMPARE_OP 2 (==) 10 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (0) 14 RETURN_VALUE 4 >> 16 LOAD_FAST 0 (a) 18 LOAD_CONST 1 (2) 20 BINARY_MULTIPLY 22 RETURN_VALUE
ãªãŒãã¿ã€ã CPythonã¯ã¹ã¿ãã¯æåã®ä»®æ³ãã·ã³ã§ãããã¬ãžã¹ã¿ã®ã³ã¬ã¯ã·ã§ã³ã§ã¯ãããŸããã ããã¯ãã¹ã¿ãã¯ã¢ãŒããã¯ãã£ã®ä»®æ³ãã·ã³çšã«Pythonã³ãŒããã³ã³ãã€ã«ãããããšãæå³ããŸãã
颿°ãåŒã³åºããšããPythonã¯2ã€ã®ã¹ã¿ãã¯ãäžç·ã«äœ¿çšããŸãã 1ã€ç®ã¯å®è¡ã¹ã¿ãã¯ã§ã2ã€ç®ã¯ãããã¯ã®ã¹ã¿ãã¯ã§ãã ã»ãšãã©ã®åŒã³åºãã¯å®è¡ã¹ã¿ãã¯ã§çºçããŸãã ãããã¯ã¹ã¿ãã¯ã¯ãçŸåšã¢ã¯ãã£ããªãããã¯ã®æ°ãããã³ãããã¯ãšã¹ã³ãŒãã«é¢é£ããä»ã®ãã©ã¡ãŒã¿ãŒã远跡ããŸãã
ãããªã¢ã«ã«é¢ããã³ã¡ã³ãããåŸ
ã¡ããŠããããããã¯ãå
¬éïŒä¿¡é Œã§ãããœãããŠã§ã¢ã®ãªãªãŒã¹ã®å®çšçåŽé¢ãã«é¢ãã
å
¬éãŠã§ãããŒã«ãæåŸ
ããŸããããã¯ãæåž«-Mail.Ru-
Stanislav Stupnikovã®åºåã·ã¹ãã ã®ããã°ã©ããŒã«ãã£ãŠå®æœãããŸãã