Python/メソッド呼び出し
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[Pythonを読む]]
#contents
*はじめに [#s49b9b76]
最後、メソッド呼び出しです。もうここまで来たら大体わかっ...
#code(Python){{
foo.method()
}}
対応するバイトコード
10 22 LOAD_NAME 1 (foo)
24 LOAD_ATTR 2 (method)
26 CALL_FUNCTION 0
*LOAD_ATTR [#k1ae9d7d]
というわけでとっかかりはLOAD_ATTRの処理部分です。
#code(C){{
TARGET(LOAD_ATTR) {
PyObject *name = GETITEM(names, oparg);
PyObject *owner = TOP();
PyObject *res = PyObject_GetAttr(owner, name);
Py_DECREF(owner);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
}}
STORE_ATTRがSetAttr呼び出していたのに対応する形でGetAttr...
#code(C){{
PyObject *
PyObject_GetAttr(PyObject *v, PyObject *name)
{
PyTypeObject *tp = Py_TYPE(v);
if (tp->tp_getattro != NULL)
return (*tp->tp_getattro)(v, name);
// 省略
}
}}
tp_getattroはPyObject_GenericGetAttrです。
#code(C){{
PyObject *
PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
{
return _PyObject_GenericGetAttrWithDict(obj, name, NU...
}
PyObject *
_PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject ...
{
PyTypeObject *tp = Py_TYPE(obj);
PyObject *descr = NULL;
PyObject *res = NULL;
descrgetfunc f;
Py_ssize_t dictoffset;
PyObject **dictptr;
Py_INCREF(name);
if (tp->tp_dict == NULL) {
if (PyType_Ready(tp) < 0)
goto done;
}
descr = _PyType_Lookup(tp, name);
f = NULL;
if (descr != NULL) {
Py_INCREF(descr);
f = descr->ob_type->tp_descr_get;
if (f != NULL && PyDescr_IsData(descr)) {
res = f(descr, obj, (PyObject *)obj->ob_type);
goto done;
}
}
if (dict == NULL) {
/* Inline _PyObject_GetDictPtr */
// 省略
}
if (dict != NULL) {
// 省略
}
if (f != NULL) {
res = f(descr, obj, (PyObject *)Py_TYPE(obj));
goto done;
}
if (descr != NULL) {
res = descr;
descr = NULL;
goto done;
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%U'",
tp->tp_name, name);
done:
Py_XDECREF(descr);
Py_DECREF(name);
return res;
}
}}
今対象にしている「method」はクラスオブジェクトの方の辞書...
*call_function (Python/ceval.c) [#zecde35b]
さてメソッド呼び出しです。バイトコードではメソッドの場合...
#code(C){{
static PyObject *
call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyO...
{
PyObject **pfunc = (*pp_stack) - oparg - 1;
PyObject *func = *pfunc;
PyObject *x, *w;
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_...
Py_ssize_t nargs = oparg - nkwargs;
PyObject **stack;
/* Always dispatch PyCFunction first, because these are
presumed to be the most frequent callable object.
*/
if (PyCFunction_Check(func)) {
// こっちじゃない
}
else {
if (PyMethod_Check(func) && PyMethod_GET_SELF(fun...
/* optimize access to bound methods */
PyObject *self = PyMethod_GET_SELF(func);
PCALL(PCALL_METHOD);
PCALL(PCALL_BOUND_METHOD);
Py_INCREF(self);
func = PyMethod_GET_FUNCTION(func);
Py_INCREF(func);
Py_SETREF(*pfunc, self);
nargs++;
}
else {
Py_INCREF(func);
}
stack = (*pp_stack) - nargs - nkwargs;
if (PyFunction_Check(func)) {
x = fast_function(func, stack, nargs, kwnames);
}
else {
x = _PyObject_FastCallKeywords(func, stack, n...
}
Py_DECREF(func);
}
// 省略
return x;
}
}}
funcがMethodObjectの場合、
+MethodObjectからFunctionObjectを取り出してfuncに設定
+*pfuncにselfを設定
+引数の数(nargs)を1足す
ということをしています。特に2つ目が巧妙で、
pfuncはポインタのポインタであり、初期状態では呼び出すオブ...
**pp_stack→
引数 ※今の場合は引数はないです
*pfunc→呼び出すオブジェクト
ということになっています。これが上で挙げた2つ目の処理によ...
**pp_stack→
引数 ※今の場合は引数はないです
*pfunc→self
となります。これによりselfを引数として渡すということが実...
*おわりに [#l43493cf]
今回はメソッド呼び出しについて見てきました。Pythonはself...
これにて「クラス定義とインスタンス生成、メソッド呼び出し...
-クラス定義とはクラス定義コードの実行(関数実行)である。...
-作成された属性辞書を使ってPyTypeObjectを作る。PyTypeObje...
-PyTypeObjectには特殊メソッドに対応するC言語の実装を設定...
-関数オブジェクトは辞書から取り出されるときにselfがバイン...
-PyObjectには直接はインスタンス辞書のメンバはない。実際に...
終了行:
[[Pythonを読む]]
#contents
*はじめに [#s49b9b76]
最後、メソッド呼び出しです。もうここまで来たら大体わかっ...
#code(Python){{
foo.method()
}}
対応するバイトコード
10 22 LOAD_NAME 1 (foo)
24 LOAD_ATTR 2 (method)
26 CALL_FUNCTION 0
*LOAD_ATTR [#k1ae9d7d]
というわけでとっかかりはLOAD_ATTRの処理部分です。
#code(C){{
TARGET(LOAD_ATTR) {
PyObject *name = GETITEM(names, oparg);
PyObject *owner = TOP();
PyObject *res = PyObject_GetAttr(owner, name);
Py_DECREF(owner);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
}}
STORE_ATTRがSetAttr呼び出していたのに対応する形でGetAttr...
#code(C){{
PyObject *
PyObject_GetAttr(PyObject *v, PyObject *name)
{
PyTypeObject *tp = Py_TYPE(v);
if (tp->tp_getattro != NULL)
return (*tp->tp_getattro)(v, name);
// 省略
}
}}
tp_getattroはPyObject_GenericGetAttrです。
#code(C){{
PyObject *
PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
{
return _PyObject_GenericGetAttrWithDict(obj, name, NU...
}
PyObject *
_PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject ...
{
PyTypeObject *tp = Py_TYPE(obj);
PyObject *descr = NULL;
PyObject *res = NULL;
descrgetfunc f;
Py_ssize_t dictoffset;
PyObject **dictptr;
Py_INCREF(name);
if (tp->tp_dict == NULL) {
if (PyType_Ready(tp) < 0)
goto done;
}
descr = _PyType_Lookup(tp, name);
f = NULL;
if (descr != NULL) {
Py_INCREF(descr);
f = descr->ob_type->tp_descr_get;
if (f != NULL && PyDescr_IsData(descr)) {
res = f(descr, obj, (PyObject *)obj->ob_type);
goto done;
}
}
if (dict == NULL) {
/* Inline _PyObject_GetDictPtr */
// 省略
}
if (dict != NULL) {
// 省略
}
if (f != NULL) {
res = f(descr, obj, (PyObject *)Py_TYPE(obj));
goto done;
}
if (descr != NULL) {
res = descr;
descr = NULL;
goto done;
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%U'",
tp->tp_name, name);
done:
Py_XDECREF(descr);
Py_DECREF(name);
return res;
}
}}
今対象にしている「method」はクラスオブジェクトの方の辞書...
*call_function (Python/ceval.c) [#zecde35b]
さてメソッド呼び出しです。バイトコードではメソッドの場合...
#code(C){{
static PyObject *
call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyO...
{
PyObject **pfunc = (*pp_stack) - oparg - 1;
PyObject *func = *pfunc;
PyObject *x, *w;
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_...
Py_ssize_t nargs = oparg - nkwargs;
PyObject **stack;
/* Always dispatch PyCFunction first, because these are
presumed to be the most frequent callable object.
*/
if (PyCFunction_Check(func)) {
// こっちじゃない
}
else {
if (PyMethod_Check(func) && PyMethod_GET_SELF(fun...
/* optimize access to bound methods */
PyObject *self = PyMethod_GET_SELF(func);
PCALL(PCALL_METHOD);
PCALL(PCALL_BOUND_METHOD);
Py_INCREF(self);
func = PyMethod_GET_FUNCTION(func);
Py_INCREF(func);
Py_SETREF(*pfunc, self);
nargs++;
}
else {
Py_INCREF(func);
}
stack = (*pp_stack) - nargs - nkwargs;
if (PyFunction_Check(func)) {
x = fast_function(func, stack, nargs, kwnames);
}
else {
x = _PyObject_FastCallKeywords(func, stack, n...
}
Py_DECREF(func);
}
// 省略
return x;
}
}}
funcがMethodObjectの場合、
+MethodObjectからFunctionObjectを取り出してfuncに設定
+*pfuncにselfを設定
+引数の数(nargs)を1足す
ということをしています。特に2つ目が巧妙で、
pfuncはポインタのポインタであり、初期状態では呼び出すオブ...
**pp_stack→
引数 ※今の場合は引数はないです
*pfunc→呼び出すオブジェクト
ということになっています。これが上で挙げた2つ目の処理によ...
**pp_stack→
引数 ※今の場合は引数はないです
*pfunc→self
となります。これによりselfを引数として渡すということが実...
*おわりに [#l43493cf]
今回はメソッド呼び出しについて見てきました。Pythonはself...
これにて「クラス定義とインスタンス生成、メソッド呼び出し...
-クラス定義とはクラス定義コードの実行(関数実行)である。...
-作成された属性辞書を使ってPyTypeObjectを作る。PyTypeObje...
-PyTypeObjectには特殊メソッドに対応するC言語の実装を設定...
-関数オブジェクトは辞書から取り出されるときにselfがバイン...
-PyObjectには直接はインスタンス辞書のメンバはない。実際に...
ページ名: