web-dev-qa-db-ja.com

co_namesとは何ですか?

description for co_names検査モジュールの読み取り:

ローカル変数の名前のタプル

ただし、実際にはco_namesはグローバル変数名のタプルであり、co_varnamesは、ローカル変数名(および引数名)のタプルです。例えば:

a = 1

def f(b):
    c = a + b

print(f.__code__.co_varnames)  # prints ('b', 'c')
print(f.__code__.co_names)     # prints ('a',)

さらに、disモジュールのドキュメントでは、多くの命令の説明がco_namesには、グローバル変数の名前が含まれています。たとえば、LOAD_GLOBALdescription 読み取り:

Co_names [namei]という名前のグローバルをスタックにロードします。

ここで何か誤解していますか?しますco_namesには「ローカル変数の名前」が本当に含まれていますか?

2017年7月17日編集

コメント/回答で述べたように、これはドキュメントのエラーのようです。報告されたバグの問題 こちら

2017年7月22日編集

プル要求 承認され、マージされるのを待っているこのドキュメントのエラーを修正します。

21
Alex

他の人がすでに言っているように、これはドキュメントエラーのようです。 コードオブジェクトのドキュメントドキュメントのinspect と明らかに矛盾します:

co_varnamesaローカル変数の名前を含むタプル(引数名で始まる); [...] co_namesは、バイトコードによって使用される名前を含むタプルです;

また、コードオブジェクトの属性co_namesおよびco_varnamesへのアクセスは、inspectに記述された内容と競合します。

>>> def f():
...     a = 1
...     b = 2
... 
>>> f.__code__.co_names
()
>>> f.__code__.co_varnames
('a', 'b')

さらに、ソースコードの CPythonのコンパイラ のコメントでは、co_varnamesがローカル変数用であることを明示的に述べています。

PyObject *u_names;     /* all names */
PyObject *u_varnames; /* local variables */

co_varnamesが表示されない理由は、上記のコードがPythonがコンパイルに使用するコンパイラオブジェクトの属性を初期化しているためですコード u_namesu_varnamesの両方が後でPyCode_New に渡されます-CPythonコードオブジェクトのコンストラクタ:

names = dict_keys_inorder(c->u->u_names, 0);
varnames = dict_keys_inorder(c->u->u_varnames, 0);

...

co = PyCode_New(..., names, varnames, ... );

そして PyCode_Newnamesおよびvarnamesco_namesおよびco_varnames属性にそれぞれ割り当てます

Py_INCREF(names);
co->co_names = names;
Py_INCREF(varnames);
co->co_varnames = varnames;

まだ行っていない場合は、 bugs.python.org でバグレポートに記入して、Python開発チームにドキュメント内のこの不整合について知らせる必要があります。

15
Christian Dean