2017-10-05 162 views
-1

据我所知__dict__ in obj.__dict__type(obj)的描述符属性,因此obj.__dict__的查询是type(obj).__dict__['__dict__'].__get__(obj)Python如何绕过普通属性查找来查找`__dict__`?

https://stackoverflow.com/a/46576009

人们很容易说,__dict__必须是一个描述符,因为 其实现为__dict__条目将要求您找到 __dict__你可以找到__dict__之前,但的Python已经 绕过正常的属性查找,找到__dict__查找其他 属性的时候,所以这并不像最初 声音一样引人注目。如果描述均与 每一个__dict__关键'__dict__'更换,__dict__仍然是容易找到。

“Python已经如何绕过普通属性查找找到__dict__”? “正常属性查找”是什么意思?

根据链接中引用的上下文,我不认为作者写这篇文章时,他提到obj.__dict__的查找是type(obj).__dict__['__dict__'].__get__(obj)

+3

我注意到了@Tim,你经常为你的问题添加一个赞美的评论。虽然在与某人面对面交谈时这当然被认为是礼貌的,但它只会给Stack Overflow上的帖子增加噪音。请参阅[_Why是否有其他用户从我的问题中删除谢谢?](https://meta.stackoverflow.com/questions/328379/why-are-fellow-users-removing-thank-yous-from-my-题)了解更多详情 –

+1

你会发现这个兴趣:https://stackoverflow.com/questions/39379351/changing-getattr-during-instantiation –

回答

3

正常属性查找通过调用__getattribute__ hook或更确切地说C-API tp_getattro slot来完成。此默认实现位于PyObject_GenericGetAttr C-API function

PyObject_GenericGetAttr的作业是调用描述符,如果它们存在,并查看实例__dict__。事实上,有一个__dict__描述,但它是__getattribute__更快刚刚访问直接实例存储结构的__dict__插槽,而这正是the actual implementation做:

if (dict == NULL) { 
    /* Inline _PyObject_GetDictPtr */ 
    dictoffset = tp->tp_dictoffset; 
    if (dictoffset != 0) { 
     if (dictoffset < 0) { 
      Py_ssize_t tsize; 
      size_t size; 

      tsize = ((PyVarObject *)obj)->ob_size; 
      if (tsize < 0) 
       tsize = -tsize; 
      size = _PyObject_VAR_SIZE(tp, tsize); 
      assert(size <= PY_SSIZE_T_MAX); 

      dictoffset += (Py_ssize_t)size; 
      assert(dictoffset > 0); 
      assert(dictoffset % SIZEOF_VOID_P == 0); 
     } 
     dictptr = (PyObject **) ((char *)obj + dictoffset); 
     dict = *dictptr; 
    } 
} 

注意内嵌_PyObject_GetDictPtr评论;这是性能优化,因为实例属性查找频繁。

如果您尝试访问instance.__dict__从Python代码,则描述符被调用;它是一个数据描述符对象,因此在实例属性被查看之前被调用。

+0

感谢。是否查找过程'__dict__'也适用于其他属性,其名称作为开始和两个下划线结尾,如'__name__','__class__','__new__','__init__','__str__','__repr__'? – Tim

+0

[查找自定义属性的名称都以两个下划线开头和结尾(例如'__madeupAttribute__')是否与查找这些特殊属性相同?](https:// stackoverflow。com/q/46594480) – Tim

+0

@Tim:不,这不是特殊名称,'__dict__'是一个特殊的名字,与它无关。每次查找不是数据描述符的属性时,属性查找过程都需要访问该特定对象*,因此访问路径得到了优化。 –