––––––––––<br>
免責事項:
この回答のドキュメントは公式のものではなく、間違っている可能性があります。
この回答は、python バージョン 3.x でのみ有効です。
–––––––––––</p>
コード オブジェクトを作成するには、関数 CodeType() に次の引数を渡す必要があります。
CodeType(
argcount, # integer
kwonlyargcount, # integer
nlocals, # integer
stacksize, # integer
flags, # integer
codestring, # bytes
consts, # tuple
names, # tuple
varnames, # tuple
filename, # string
name, # string
firstlineno, # integer
lnotab, # bytes
freevars, # tuple
cellvars # tuple
)
ここで、各引数の意味を説明しようと思います。
argcount
関数に渡される引数の数 (*args と **kwargs は含まれません)。
kwonlyargcountキーワードのみの引数
の数。
nlocals
ローカル変数の数。
つまり、グローバル名を除くすべての変数とパラメーター (*args と **kwargs を含む)。
stacksize
コードが必要とするスタック (仮想マシン スタック) の量。
それがどのように機能するかを理解したい場合は、公式ドキュメントを参照してください。
flags
コード オブジェクトについて何かを示すビットマップ:
1 –> コードが最適化された
2 –> newlocals: 新しいローカル名前空間 (関数など) がある
4 –> コードは任意の数の位置引数を受け入れる (*args は使用)
8 –> コードは任意の数のキーワード引数を受け入れます (*kwargs が使用されます)
32 –> コードはジェネレーターです
その他のフラグは、古い python バージョンで使用されているか、__ future __ からインポートされたものを示すためにアクティブ化されています
codestring
理解を深めたい場合は
、バイトコード命令を表す一連のバイト。ドキュメントを参照してください(上記と同じ) 。
consts
バイトコードで使用されるリテラルを含むタプル (事前に計算された数値、タプル、文字列など)
バイトコードで使用される名前
を含むタプル。
この名前は、グローバル変数、関数、クラス、またはオブジェクトからロードされた属性です。
varnames
バイトコードで使用されるローカル名を含むタプル (最初に引数、次にローカル変数)
filename
コードがコンパイルされたファイル名です。
それはあなたが望むものである可能性があり、あなたはこれについて自由に嘘をつくことができます. ;)
name
関数の名前を与えます。また、これは好きなように指定できますが、注意してください:
これはトレースバックに表示される名前です。名前が不明な場合、トレースバックが不明になる
可能性があります。
firstlineno
関数の最初の行 (ソース コードをコンパイルした場合のデバッグ用)
lnotab
バイトコードのオフセットを行番号に関連付けるバイトのマッピング。
(これもデバッグ目的だと思いますが、これに関するドキュメントはほとんどありません)
freevars
自由変数の名前を含むタプル。
フリー変数は、コード オブジェクトが定義された名前空間で宣言された変数であり、ネストされた関数が宣言されたときに使用されます。
これはモジュール レベルでは発生しません。その場合、自由変数はグローバル変数でもあるためです。
cellvars
ネストされた関数によって参照されるローカル変数の名前を含むタプル。
––––––––––––<br>
例:
次の例は、上で述べたことの意味を明確にするはずです。
注: 上記の完成したコード オブジェクトの属性にはco_プレフィックスが
あり、関数は実行可能な本体を__code__属性に格納します。
––––––––––––<br>
1番目の例
def F(a,b):
global c
k=a*c
w=10
p=(1,"two",3)
print(F.__code__.co_argcount)
print(F.__code__.co_nlocals , F.__code__.co_varnames)
print(F.__code__.co_stacksize)
print(F.__code__.co_flags)
print(F.__code__.co_names)
print(F.__code__.co_consts)
出力:
2
5 ('a', 'b', 'k', 'w', 'p')
3
67
('c' ,)
(None, 10, 1, 'two'. 3, (1, 'two', 3))
この関数には 2 つの引数が渡されます ("a"、"b")
この関数には、2 つのパラメーター ("a"、"b") と 3 つのローカル変数 ("k"、"w"、"p") があります。
関数のバイトコードを逆アセンブルすると、次のようになります。
3 0 LOAD_FAST 0 (a) #stack: ["a"]
3 LOAD_GLOBAL 0 (c) #stack: ["a","c"]
6 BINARY_MULTIPLY #stack: [result of a*c]
7 STORE_FAST 2 (k) #stack: []
4 10 LOAD_CONST 1 (10) #stack: [10]
13 STORE_FAST 3 (w) #stack: []
5 16 LOAD_CONST 5 ((1, 'two', 3)) #stack: [(1,"two",3)]
19 STORE_FAST 4 (p) #stack: []
22 LOAD_CONST 0 (None) #stack: [None]
25 RETURN_VALUE #stack: []
chile が関数を実行していることに気付くと思いますが、スタック内の要素が 3 つを超えることはありません (この場合、タプルはその長さとしてカウントされます)。
フラグの値はdec 67 = bin 1000011 = bin 1000000 +10 +1 = dec 64 +2 +1 なので、
- コードが最適化されている (自動生成されたコードのほとんどがそうであるように)
- 関数バイトコードのローカル名前空間の変更の実行中に
- 64? 実際、私はその意味が何であるかを知りません
関数で使用される唯一のグローバル名は "c" で、co_names に格納されます。
使用するすべての明示的なリテラルは co_consts に格納されます。
- None は関数の戻り値です
- w に数値 10 を明示的に割り当てます。
- (1, 'two', 3) を p に明示的に代入します
- タプルが定数の場合、そのタプルの各要素は定数であるため、1、"2"、3 は定数です。
––––––––––––<br>
2 番目の例
ModuleVar="hi"
def F():
FunctionVar=106
UnusedVar=ModuleVar
def G():
return (FunctionVar,ModuleVar)
print(G.__code__.co_freevars)
print(G.__code__.co_names)
F()
print(F.__code__.co_cellvars)
print(F.__code__.co_freevars)
print(F.__code__.co_names)
出力:
('FunctionVar',)
('ModuleVar',)
('FunctionVar',)
()
('print', '__code__', 'co_freevars', 'co_names', 'ModuleVar')
出力の意味は次のとおりです。
1 行目と 2 行目は F が実行されたときに表示されるため、G コードの co_freevars と co_names が表示さ
れ
ます。グローバルとして。
次の 3 行は、F コードの co_cellvars、co_freevars、および co_names 属性に関するものです。
「FunctionVar」は G のネストされた関数で参照されるため、cellvar としてマークされ、
「ModuleVar」は F が作成された名前空間にありますが、モジュール変数な
ので、freevar としてマークされませんが、グローバル名で見つかります。
また、組み込み関数 print は names でマークされ、F で使用される属性のすべての名前がマークされます。
––––––––––––<br>
3番目の例
これは動作するコード オブジェクトの初期化です。
これは役に立ちませんが、この関数で必要なことはすべて実行できます。
MyCode= CodeType(
0,
0,
0,
3,
64,
bytes([101, 0, 0, #Load print function
101, 1, 0, #Load name 'a'
101, 2, 0, #Load name 'b'
23, #Take first two stack elements and store their sum
131, 1, 0, #Call first element in the stack with one positional argument
1, #Pop top of stack
101, 0, 0, #Load print function
101, 1, 0, #Load name 'a'
101, 2, 0, #Load name 'b'
20, #Take first two stack elements and store their product
131, 1, 0, #Call first element in the stack with one positional argument
1, #Pop top of stack
100, 0, 0, #Load constant None
83]), #Return top of stack
(None,),
('print', 'a', 'b'),
(),
'PersonalCodeObject',
'MyCode',
1,
bytes([14,1]),
(),
() )
a=2
b=3
exec(MyCode) # code prints the sum and the product of "a" and "b"
出力:
5
6