所以我试图了解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>
那么如何知道它的实现呢?
答案 0 :(得分:4)
__dir__
是一个特殊方法,因此请查看该类型,至少在Python 3中是这样的:
>>> 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:
对于自定义类,只有在对象类型上定义的特殊方法的隐式调用才能保证正常工作,而不是在对象的实例字典中。
这正是_PyObject_LookupSpecial()
函数的作用,请参阅the typeobject.c
source code:
res = _PyType_LookupId(Py_TYPE(self), attrid);
Py_TYPE()
调用是重要的部分,__dir__
在类型上查找。
__dir__
方法在object
类型上实现,并由函数类型继承,因此实现位于object_dir()
function。
对于Python 2,dir()
implementation is more elaborate,实际上也委托给其他函数!对于函数对象,它委托给_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()
递归地将类层次结构属性合并到最终结果中。
答案 1 :(得分:1)
您正在查看的代码来自最新的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);
}
要在Python 3中实现object.__dir__
,请参阅Objects / typeobject.c中的object___dir___impl
。