目次
コード オブジェクトのデータ構造
コードオブジェクトの詳細な分析
分析には特に python3.5 のソース コードを使用します。cpython 仮想マシンの具体的な実装は次のとおりです (インクルード/コード) .h ):
freevars & cellvars
stacksize
ホームページ バックエンド開発 Python チュートリアル Python 仮想マシンにおけるコード オブジェクトの役割は何ですか?

Python 仮想マシンにおけるコード オブジェクトの役割は何ですか?

May 10, 2023 pm 05:46 PM
python

コード オブジェクトのデータ構造

typedef struct {
    PyObject_HEAD
    int co_argcount;		/* #arguments, except *args */
    int co_kwonlyargcount;	/* #keyword only arguments */
    int co_nlocals;		/* #local variables */
    int co_stacksize;		/* #entries needed for evaluation stack */
    int co_flags;		/* CO_..., see below */
    PyObject *co_code;		/* instruction opcodes */
    PyObject *co_consts;	/* list (constants used) */
    PyObject *co_names;		/* list of strings (names used) */
    PyObject *co_varnames;	/* tuple of strings (local variable names) */
    PyObject *co_freevars;	/* tuple of strings (free variable names) */
    PyObject *co_cellvars;      /* tuple of strings (cell variable names) */
    /* The rest aren't used in either hash or comparisons, except for
       co_name (used in both) and co_firstlineno (used only in
       comparisons).  This is done to preserve the name and line number
       for tracebacks and debuggers; otherwise, constant de-duplication
       would collapse identical functions/lambdas defined on different lines.
    */
    unsigned char *co_cell2arg; /* Maps cell vars which are arguments. */
    PyObject *co_filename;	/* unicode (where it was loaded from) */
    PyObject *co_name;		/* unicode (name, for reference) */
    int co_firstlineno;		/* first source line number */
    PyObject *co_lnotab;	/* string (encoding addr<->lineno mapping) See
				   Objects/lnotab_notes.txt for details. */
    void *co_zombieframe;     /* for optimization only (see frameobject.c) */
    PyObject *co_weakreflist;   /* to support weakrefs to code objects */
} PyCodeObject;
ログイン後にコピー

コード オブジェクトの各フィールドの役割は次のとおりです。

  • まず、次の概念を理解する必要があります。コード ブロック: いわゆるコード ブロックは、小さな Python コードが小さな単位として実行されます。 Python の一般的なコード ブロックには、関数本体、クラス定義、モジュールが含まれます。

  • argcount、これはコード ブロック内のパラメーターの数を表します。関数には上記の pycdemo.py などのパラメーターがある可能性があるため、このパラメーターは関数本体のコード ブロックでのみ役立ちます。は関数ではなくモジュールです。このパラメータの対応する値は 0 です。

  • co_code、このオブジェクトの特定のコンテンツは、実際の Python バイトコードを格納するバイト シーケンスです。これは主に Python 仮想マシンの実行に使用され、この記事には含まれません。詳細な分析。

  • co_consts、このフィールドはリスト タイプのフィールドで、主に "__main__" や上記の 100 などの文字列定数と数値定数が含まれます。

  • co_filename、このフィールドの意味は、対応するソース ファイルのファイル名です。

  • co_firstlineno, このフィールドの意味は、Python ソース ファイルのコードの最初の行に表示される行数です。このフィールドはデバッグ時に非常に重要です。

  • co_flags、このフィールドの主な意味は、このコード オブジェクトのタイプを識別することです。 0x0080 はこのブロックがコルーチンであることを示し、0x0010 はこのコード オブジェクトがネストされていることを示します。

  • co_lnotab、このフィールドの意味は主に、各バイトコード命令に対応するソースコード行数を計算するために使用されます。

  • co_varnames、このフィールドの主な意味は、コード オブジェクト内でローカルに定義された名前を表すことです。

  • co_names は co_varnames の逆で、ローカルに定義されていないがコード オブジェクトで使用される名前を表します。

  • co_nlocals、このフィールドは、コード オブジェクト内でローカルに使用される変数の数を示します。

  • co_stackszie、Python 仮想マシンはスタック コンピューターであるため、このパラメーターの値は、このスタックに必要な最大値を示します。

  • co_cellvars、co_freevars、これら 2 つのフィールドは主にネストされた関数と関数クロージャに関連しています。このフィールドについては後続の記事で詳しく説明します。

コードオブジェクトの詳細な分析

次に、いくつかの実践的な例を使用して、特定のコード オブジェクトを分析します。

import dis
import binascii
import types

d = 10


def test_co01(c):
    a = 1
    b = 2
    return a + b + c + d
ログイン後にコピー

前の記事では、関数にはコード オブジェクト オブジェクトが含まれると述べましたが、test_co01 (完全なコードについては co01 を参照) のコード オブジェクト オブジェクトの出力結果は次のとおりです。

    #フィールド argcount の値は 1 に等しく、関数が 1 つのパラメーターを持つことを示します。この関数 test_co01 には、互いに対応するパラメーター c があります。
  • フィールド nlocals の値は 3 に等しく、合計 3 つの関数ローカル変数 a、b、c が関数 test_co01 に実装されていることを示します。
  • フィールド名はコード内の co_names に対応します。前の定義によれば、グローバル変数 d は関数 test_co01 で使用されていますが、関数内では定義されていません。
  • フィールド変数名、これはローカル定義で使用される変数を表します。関数 test_co01 には 3 つの主要な変数 a、b、c があります。
  • フィールド filename は、Python ファイルのアドレスです。
  • フィールド firstlineno は、関数の最初の行が、対応する Python コードの 8 行目に現れることを示します。
  • Flags フィールドの詳細な分析

分析には特に python3.5 のソース コードを使用します。cpython 仮想マシンの具体的な実装は次のとおりです (インクルード/コード) .h ):

code
   argcount 1
   nlocals 3
   stacksize 2
   flags 0043 0x43
   code b&#39;6401007d01006402007d02007c01007c0200177c0000177400001753&#39;
  9           0 LOAD_CONST               1 (1)
              3 STORE_FAST               1 (a)

 10           6 LOAD_CONST               2 (2)
              9 STORE_FAST               2 (b)

 11          12 LOAD_FAST                1 (a)
             15 LOAD_FAST                2 (b)
             18 BINARY_ADD
             19 LOAD_FAST                0 (c)
             22 BINARY_ADD
             23 LOAD_GLOBAL              0 (d)
             26 BINARY_ADD
             27 RETURN_VALUE
   consts
      None
      1
      2
   names (&#39;d&#39;,)
   varnames (&#39;c&#39;, &#39;a&#39;, &#39;b&#39;)
   freevars ()
   cellvars ()
   filename &#39;/tmp/pycharm_project_396/co01.py&#39;
   name &#39;test_co01&#39;
   firstlineno 8
   lnotab b&#39;000106010601&#39;
ログイン後にコピー

flags フィールドと上記の各マクロ定義の間で & 演算が実行され、結果が 0 より大きい場合、対応する条件が満たされていることを意味します。

上記のマクロ定義の意味は次のとおりです:

  • CO_OPTIMIZED

    、このフィールドは、関数ローカルを使用してコード オブジェクトが最適化されていることを示します。定義された変数。

  • CO_NEWLOCALS

    、このフィールドの意味は、このコード オブジェクトのコードが実行されると、スタック内の f_locals オブジェクトの dict オブジェクトが作成されることです。フレーム。

  • CO_VARARGS

    は、このコード オブジェクトに位置パラメータが含まれるかどうかを示します。

  • CO_VARKEYWORDS

    は、このコード オブジェクトにキーワード パラメーターが含まれているかどうかを示します。

  • CO_NESTED

    、このコード オブジェクトがネストされた関数であることを示します。

  • CO_GENERATOR

    、このコード オブジェクトがジェネレーターであることを示します。

  • CO_COROUTINE

    。このコード オブジェクトがコルーチン関数であることを示します。

  • CO_ITERABLE_COROUTINE

    。コード オブジェクトが反復可能なコルーチン関数であることを示します。

  • CO_NOFREE

    、これは、freevars と cellvars がないこと、つまり関数クロージャーがないことを意味します。

  • 次に、前の関数 test_co01 のフラグを分析しましょう。その対応する値は 0x43 に等しく、これは、この関数が 3 つの特性 (CO_NEWLOCALS、CO_​​OPTIMIZED、CO_NOFREE) を満たすことを意味します。

freevars & cellvars

我们使用下面的函数来对这两个字段进行分析:

def test_co02():
    a = 1
    b = 2

    def g():
        return a + b
    return a + b + g()
ログイン後にコピー

上面的函数的信息如下所示(完整代码见co02):

code
   argcount 0
   nlocals 1
   stacksize 3
   flags 0003 0x3
   code
      b&#39;640100890000640200890100870000870100660200640300640400860000&#39;
      b&#39;7d0000880000880100177c00008300001753&#39;
 15           0 LOAD_CONST               1 (1)
              3 STORE_DEREF              0 (a)

 16           6 LOAD_CONST               2 (2)
              9 STORE_DEREF              1 (b)

 18          12 LOAD_CLOSURE             0 (a)
             15 LOAD_CLOSURE             1 (b)
             18 BUILD_TUPLE              2
             21 LOAD_CONST               3 (<code object g at 0x7f133ff496f0, file "/tmp/pycharm_project_396/co01.py", line 18>)
             24 LOAD_CONST               4 (&#39;test_co02.<locals>.g&#39;)
             27 MAKE_CLOSURE             0
             30 STORE_FAST               0 (g)

 20          33 LOAD_DEREF               0 (a)
             36 LOAD_DEREF               1 (b)
             39 BINARY_ADD
             40 LOAD_FAST                0 (g)
             43 CALL_FUNCTION            0 (0 positional, 0 keyword pair)
             46 BINARY_ADD
             47 RETURN_VALUE
   consts
      None
      1
      2
      code
         argcount 0
         nlocals 0
         stacksize 2
         flags 0013 0x13
         code b&#39;8800008801001753&#39;
 19           0 LOAD_DEREF               0 (a)
              3 LOAD_DEREF               1 (b)
              6 BINARY_ADD
              7 RETURN_VALUE
         consts
            None
         names ()
         varnames ()
         freevars (&#39;a&#39;, &#39;b&#39;)
         cellvars ()
         filename &#39;/tmp/pycharm_project_396/co01.py&#39;
         name &#39;g&#39;
         firstlineno 18
         lnotab b&#39;0001&#39;
      &#39;test_co02.<locals>.g&#39;
   names ()
   varnames (&#39;g&#39;,)
   freevars ()
   cellvars (&#39;a&#39;, &#39;b&#39;)
   filename &#39;/tmp/pycharm_project_396/co01.py&#39;
   name &#39;test_co02&#39;
   firstlineno 14
   lnotab b&#39;0001060106021502&#39;
ログイン後にコピー

从上面的输出我们可以看到的是,函数 test_co02 的 cellvars 为 ('a', 'b'),函数 g 的 freevars 为 ('a', 'b'),cellvars 表示在其他函数当中会使用本地定义的变量,freevars 表示本地会使用其他函数定义的变量。

再来分析一下函数 test_co02 的 flags,他的 flags 等于 0x3 因为有闭包的存在因此 flags 不会存在 CO_NOFREE,也就是少了值 0x0040 。

stacksize

这个字段存储的是在函数在被虚拟机执行的时候所需要的最大的栈空间的大小,这也是一种优化手段,因为在知道所需要的最大的栈空间,所以可以在函数执行的时候直接分配指定大小的空间不需要在函数执行的时候再去重新扩容。

def test_stack():
    a = 1
    b = 2
    return a + b
ログイン後にコピー

上面的代码相关字节码等信息如下所示:

code
   argcount 0
   nlocals 2
   stacksize 2
   flags 0043 0x43
   code b&#39;6401007d00006402007d01007c00007c01001753&#39;
   #					  字节码指令		 # 字节码指令参数 # 参数对应的值
 24           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (a)

 25           6 LOAD_CONST               2 (2)
              9 STORE_FAST               1 (b)

 26          12 LOAD_FAST                0 (a)
             15 LOAD_FAST                1 (b)
             18 BINARY_ADD
             19 RETURN_VALUE
   consts
      None # 下标等于 0 的常量
      1 	 # 下标等于 1 的常量
      2		 # 下标等于 2 的常量
   names ()
   varnames (&#39;a&#39;, &#39;b&#39;)
   freevars ()
   cellvars ()
ログイン後にコピー

我们现在来模拟一下执行过程,在模拟之前我们首先来了解一下上面几条字节码的作用:

LOAD_CONST,将常量表当中的下标等于 i 个对象加载到栈当中,对应上面的代码 LOAD_CONST 的参数 i = 1。因此加载测常量等于 1 。因此现在栈空间如下所示:

Python 仮想マシンにおけるコード オブジェクトの役割は何ですか?

STORE_FAST,将栈顶元素弹出并且保存到 co_varnames 对应的下标当中,根据上面的字节码参数等于 0 ,因此将 1 保存到 co_varnames[0] 对应的对象当中。

Python 仮想マシンにおけるコード オブジェクトの役割は何ですか?

LOAD_CONST,将下标等于 2 的常量加载进入栈中。

Python 仮想マシンにおけるコード オブジェクトの役割は何ですか?

STORE_FAST,将栈顶元素弹出,并且保存到 varnames 下标为 1 的对象。

Python 仮想マシンにおけるコード オブジェクトの役割は何ですか?

LOAD_FAST,是取出 co_varnames 对应下标的数据,并且将其压入栈中。我们直接连续执行两个 LOAD_FAST 之后栈空间的布局如下:

Python 仮想マシンにおけるコード オブジェクトの役割は何ですか?

BINARY_ADD,这个字节码指令是将栈空间的两个栈顶元素弹出,然后将两个数据进行相加操作,然后将相加得到的结果重新压入栈中。

Python 仮想マシンにおけるコード オブジェクトの役割は何ですか?

RETURN_VALUE,将栈顶元素弹出并且作为返回值返回。

从上面的整个执行过程来看整个栈空间使用的最大的空间长度为 2 ,因此 stacksize = 2 。

以上がPython 仮想マシンにおけるコード オブジェクトの役割は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHPおよびPython:さまざまなパラダイムが説明されています PHPおよびPython:さまざまなパラダイムが説明されています Apr 18, 2025 am 12:26 AM

PHPは主に手順プログラミングですが、オブジェクト指向プログラミング(OOP)もサポートしています。 Pythonは、OOP、機能、手続き上のプログラミングなど、さまざまなパラダイムをサポートしています。 PHPはWeb開発に適しており、Pythonはデータ分析や機械学習などのさまざまなアプリケーションに適しています。

PHPとPythonの選択:ガイド PHPとPythonの選択:ガイド Apr 18, 2025 am 12:24 AM

PHPはWeb開発と迅速なプロトタイピングに適しており、Pythonはデータサイエンスと機械学習に適しています。 1.PHPは、単純な構文と迅速な開発に適した動的なWeb開発に使用されます。 2。Pythonには簡潔な構文があり、複数のフィールドに適しており、強力なライブラリエコシステムがあります。

PHPとPython:彼らの歴史を深く掘り下げます PHPとPython:彼らの歴史を深く掘り下げます Apr 18, 2025 am 12:25 AM

PHPは1994年に発信され、Rasmuslerdorfによって開発されました。もともとはウェブサイトの訪問者を追跡するために使用され、サーバー側のスクリプト言語に徐々に進化し、Web開発で広く使用されていました。 Pythonは、1980年代後半にGuidovan Rossumによって開発され、1991年に最初にリリースされました。コードの読みやすさとシンプルさを強調し、科学的コンピューティング、データ分析、その他の分野に適しています。

Python vs. JavaScript:学習曲線と使いやすさ Python vs. JavaScript:学習曲線と使いやすさ Apr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Sublime Code Pythonを実行する方法 Sublime Code Pythonを実行する方法 Apr 16, 2025 am 08:48 AM

PythonコードをSublimeテキストで実行するには、最初にPythonプラグインをインストールし、次に.pyファイルを作成してコードを書き込み、Ctrl Bを押してコードを実行する必要があります。コードを実行すると、出力がコンソールに表示されます。

vscodeでコードを書く場所 vscodeでコードを書く場所 Apr 15, 2025 pm 09:54 PM

Visual Studioコード(VSCODE)でコードを作成するのはシンプルで使いやすいです。 VSCODEをインストールし、プロジェクトの作成、言語の選択、ファイルの作成、コードの書き込み、保存して実行します。 VSCODEの利点には、クロスプラットフォーム、フリーおよびオープンソース、強力な機能、リッチエクステンション、軽量で高速が含まれます。

Visual StudioコードはPythonで使用できますか Visual StudioコードはPythonで使用できますか Apr 15, 2025 pm 08:18 PM

VSコードはPythonの書き込みに使用でき、Pythonアプリケーションを開発するための理想的なツールになる多くの機能を提供できます。ユーザーは以下を可能にします。Python拡張機能をインストールして、コードの完了、構文の強調表示、デバッグなどの関数を取得できます。デバッガーを使用して、コードを段階的に追跡し、エラーを見つけて修正します。バージョンコントロールのためにGitを統合します。コードフォーマットツールを使用して、コードの一貫性を維持します。糸くずツールを使用して、事前に潜在的な問題を発見します。

メモ帳でPythonを実行する方法 メモ帳でPythonを実行する方法 Apr 16, 2025 pm 07:33 PM

メモ帳でPythonコードを実行するには、Python実行可能ファイルとNPPEXECプラグインをインストールする必要があります。 Pythonをインストールしてパスを追加した後、nppexecプラグインでコマンド「python」とパラメーター "{current_directory} {file_name}"を構成して、メモ帳のショートカットキー「F6」を介してPythonコードを実行します。

See all articles