__dir__ 是如何实现的,我应该如何知道它?
How is __dir__ implemented exactly, and how should I know it?
所以我想知道 dir()
函数的详细信息。首先我查看了它的实现:
https://github.com/python/cpython/blob/e76daebc0c8afa3981a4c5a8b54537f756e805de/Objects/object.c#L1450-L1477
/* Helper for PyObject_Dir: object introspection. */
static PyObject *
_dir_object(PyObject *obj)
{
PyObject *result, *sorted;
PyObject *dirfunc = _PyObject_LookupSpecial(obj, &PyId___dir__);
assert(obj);
if (dirfunc == NULL) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError, "object does not provide __dir__");
return NULL;
}
/* use __dir__ */
result = _PyObject_CallNoArg(dirfunc);
Py_DECREF(dirfunc);
if (result == NULL)
return NULL;
/* return sorted(result) */
sorted = PySequence_List(result);
Py_DECREF(result);
if (sorted == NULL)
return NULL;
if (PyList_Sort(sorted)) {
Py_DECREF(sorted);
return NULL;
}
return sorted;
}
并且发现_dir_object
函数本身并没有做任何工作,而是调用了内省对象的__dir__
方法。
>>> def test(): pass
>>> test.__dir__
<built-in method __dir__ of function object at 0x10ee57ae8>
那么如何知道执行情况呢?
__dir__
是特殊方法,所以查了一下类型,至少在Python3:
>>> type(test)
<class 'function'>
>>> '__dir__' in dir(type(test))
True
>>> type(test).__dir__
<method '__dir__' of 'object' objects>
>>> dir(test) == sorted(type(test).__dir__(test))
True
查看数据模型的Special method lookup section:
For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.
这正是 _PyObject_LookupSpecial()
函数的作用,参见 the typeobject.c
source code:
res = _PyType_LookupId(Py_TYPE(self), attrid);
那里的 Py_TYPE()
调用是重要的部分,__dir__
在 type.
上查找
__dir__
方法是在object
类型上实现的,被function类型继承,所以实现在object_dir()
function.
为Python 2、dir()
implementation is more elaborate, and actually also delegates to other functions! For function objects, it delegates to the _generic_dir()
function。此函数参考类型的__dict__
:
/* Merge in attrs reachable from its class. */
itsclass = PyObject_GetAttrString(obj, "__class__");
if (itsclass == NULL)
/* XXX(tomer): Perhaps fall back to obj->ob_type if no
__class__ exists? */
PyErr_Clear();
else {
if (merge_class_dict(dict, itsclass) != 0)
goto error;
}
其中 merge_class_dict()
递归地将 class 层次结构属性合并到最终结果中。
您正在查看的代码来自最近的 Python 版本,但您正在测试旧版本。
在新版本中,自动为所有类型提供实现 __dir__
。
在旧版本中,除非手动提供,否则对象没有__dir__
。然后实施会在 _dir_object
中考虑到这一点。这是来自 Python 2.7:
if (dirfunc == NULL) {
/* use default implementation */
if (PyModule_Check(obj))
result = _specialized_dir_module(obj);
else if (PyType_Check(obj) || PyClass_Check(obj))
result = _specialized_dir_type(obj);
else
result = _generic_dir(obj);
}
Python3中object.__dir__
的实现见Objects/typeobject.c中的object___dir___impl
所以我想知道 dir()
函数的详细信息。首先我查看了它的实现:
https://github.com/python/cpython/blob/e76daebc0c8afa3981a4c5a8b54537f756e805de/Objects/object.c#L1450-L1477
/* Helper for PyObject_Dir: object introspection. */
static PyObject *
_dir_object(PyObject *obj)
{
PyObject *result, *sorted;
PyObject *dirfunc = _PyObject_LookupSpecial(obj, &PyId___dir__);
assert(obj);
if (dirfunc == NULL) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError, "object does not provide __dir__");
return NULL;
}
/* use __dir__ */
result = _PyObject_CallNoArg(dirfunc);
Py_DECREF(dirfunc);
if (result == NULL)
return NULL;
/* return sorted(result) */
sorted = PySequence_List(result);
Py_DECREF(result);
if (sorted == NULL)
return NULL;
if (PyList_Sort(sorted)) {
Py_DECREF(sorted);
return NULL;
}
return sorted;
}
并且发现_dir_object
函数本身并没有做任何工作,而是调用了内省对象的__dir__
方法。
>>> def test(): pass
>>> test.__dir__
<built-in method __dir__ of function object at 0x10ee57ae8>
那么如何知道执行情况呢?
__dir__
是特殊方法,所以查了一下类型,至少在Python3:
>>> type(test)
<class 'function'>
>>> '__dir__' in dir(type(test))
True
>>> type(test).__dir__
<method '__dir__' of 'object' objects>
>>> dir(test) == sorted(type(test).__dir__(test))
True
查看数据模型的Special method lookup section:
For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.
这正是 _PyObject_LookupSpecial()
函数的作用,参见 the typeobject.c
source code:
res = _PyType_LookupId(Py_TYPE(self), attrid);
那里的 Py_TYPE()
调用是重要的部分,__dir__
在 type.
__dir__
方法是在object
类型上实现的,被function类型继承,所以实现在object_dir()
function.
为Python 2、dir()
implementation is more elaborate, and actually also delegates to other functions! For function objects, it delegates to the _generic_dir()
function。此函数参考类型的__dict__
:
/* Merge in attrs reachable from its class. */
itsclass = PyObject_GetAttrString(obj, "__class__");
if (itsclass == NULL)
/* XXX(tomer): Perhaps fall back to obj->ob_type if no
__class__ exists? */
PyErr_Clear();
else {
if (merge_class_dict(dict, itsclass) != 0)
goto error;
}
其中 merge_class_dict()
递归地将 class 层次结构属性合并到最终结果中。
您正在查看的代码来自最近的 Python 版本,但您正在测试旧版本。
在新版本中,自动为所有类型提供实现 __dir__
。
在旧版本中,除非手动提供,否则对象没有__dir__
。然后实施会在 _dir_object
中考虑到这一点。这是来自 Python 2.7:
if (dirfunc == NULL) {
/* use default implementation */
if (PyModule_Check(obj))
result = _specialized_dir_module(obj);
else if (PyType_Check(obj) || PyClass_Check(obj))
result = _specialized_dir_type(obj);
else
result = _generic_dir(obj);
}
Python3中object.__dir__
的实现见Objects/typeobject.c中的object___dir___impl