如何在不装箱的情况下动态访问 python 中的对象属性?

How to dynamically access object attributes in python without boxing?

getattr(dir,"__name__") is dir.__name__ 的计算结果为 False - 是否有 getattr 的替代方法会产生 True

built-in 函数的 __name__ 属性是 implemented (on the CPython reference interpreter) as a property(从技术上讲,是一个 get-set 描述符),不是以 [=70] 的形式存储为属性=]对象。

属性的作用类似于属性,但在请求值时会调用一个函数,在本例中,the function converts the C-style string name of the function to a Python str on demand. So each time you look up dir.__name__, you get freshly constructed str representing the data; ,这意味着 没有 方法is 检查通过;甚至 dir.__name__ is dir.__name__ returns False,因为每次查找 __name__ return 都会生成一个新的 str.

该语言不保证 __name__ 的实现方式,因此您不应假设它每次 return 都是同一个对象。很少有语言保证的单例(NoneTrueFalseEllipsisNotImplemented 是大佬,所有 类 都有唯一身份);如果 is 不是您控制创建的对象,那么假设 is 可以处理不在该集合中的任何对象是一个坏主意。如果要检查 是否相同,请使用 == 进行测试,而不是 is.

更新以解决遍历 python 对象的任意图而不会被动态生成对象的描述符和其他东西(如 __getattr__)挂起 (因此不应调用来描述静态图):

The inspect.getattr_static function should let you "traverse an arbitrary graph of python objects reachable from a starting one while assuming as little possible about the types of objects and the implementation of their attributes" (as )。当属性实际上是一个属性时,它 return 是值,但它不会触发描述符的动态查找(如 @property)、__getattr____getattribute__。因此 inspect.getattr_static(dir, '__name__') 将 return CPython 用于实现 __name__getset_descriptor 而无需实际检索字符串。在 __name__ 是真实属性的不同对象上(例如 inspect 模块本身),它将 return 属性(inspect.getattr_static(inspect, '__name__') returns 'inspect').

虽然它并不完美(某些属性实际上可能由真实的 Python 对象支持,而不是动态生成的对象,否则您无法访问),但它至少是一个可行的解决方案;你不会无意中创建新对象,也不会陷入 属性 查找的无限循环(例如,每个可调用对象都可以 __call__ 永远查找它,将自己包裹起来并就这样结束了),所以你至少可以得到一个解决方案,它主要准确地反映了对象图,并且不会以递归的方式结束。

值得注意的是,它将正确地保留身份语义。如果两个对象具有相同的属性(按标识),则结果将按预期匹配。如果两个对象共享一个描述符(例如 __name__ 用于所有 built-in 函数,例如 bindir),那么它 return 就是描述符本身,它将匹配身份。如果您拥有的是属性或描述符,它就可以完成这一切,而无需预先知道。