Greetings, I am trying to emulate attribute lookup, and want to test if symbol found in __dict__ is an attribute or not in python code (i.e.: does its have a `tp_descr_get` slot?) Reading the documentation carefully, I am supposed to test if the attribute has a `.__get__` method; however, I see no way to test for this properly (easily). Currently the only way I know to test for this is (See code at end of this message): any('__get__' in m.__dict__ for m in type(v).__mro__) Which seems terribly inefficient. The documentation at: https://docs.python.org/2/howto/descriptor.html https://docs.python.org/3/howto/descriptor.html Both says: """ For classes, the machinery is in type.__getattribute__() which transforms B.x into B.__dict__['x'].__get__(None, B). In pure Python, it looks like: def __getattribute__(self, key): "Emulate type_getattro() in Objects/typeobject.c" v = object.__getattribute__(self, key) if hasattr(v, '__get__'): return v.__get__(None, self) return v """ However, the call to `hasattr(v, '__get__')` appears to me to be incorrect. The question is *NOT* whether 'v' has an attribute '__get__'; *BUT* whether `v` has a symbol `__get__` in any of the classes in it's method resolution order. Looking at `type_getattro` in "Objects/typeobject.c" here: https://github.com/python/cpython/blob/master/Objects/typeobject.c#L3177 Reads: meta_get = Py_TYPE(meta_attribute)->tp_descr_get So I really want to know if the `tp_descr_get` slot is set or not. (Which is a different question than whether `v` has a `__get__` attribute). The code below shows that: 1. The valid value of `Point.y` is <Not_A_Descriptor> 2. The valid value is returned by `Point.y`, `type.__getattribute__(Point, y)`, and `fixed__Type__getattribute` 3. The invalid value of `Point.y` is `2` as returned by the [emulated] `__getattribute__` documented https://docs.python.org/3/howto/descriptor.html So I am requesting: 1. An efficient python way to test for `tp_descr_get` slot (and other descriptor) slots. 2. Fix the documentation referenced above. Thanks, Joy Diamond. NOTE #1: This email describes the very subtle difference between whether an instance has a `__get__` symbol or not, which I believe is *NOT* the same question as whether `hasattr(instance, "__get__")` returns true or not. The first question is does it have the symbol `__get_` [Which python put in the `tp_descr_slot`] while `hasattr` answers the question does it have the `__get__` attribute. NOTE #2: Also using `hasattr(type(v), "__get__")` would not answer the question I want, because then it might find a `__get__` method in the meta-class of `type(v)` which again would return an incorrect answer. Example program that shows that using `hasattr(v, '__get__')` is not a valid way to test if something is a descriptor (works in python 2, python 3, and pypy): def get_1(self, a, b): return 1 def get_2(a, b): return 2 class Descriptor(object): __get__ = get_1 class Not_A_Descriptor(object): def __init__(self): self.__get__ = get_2 def __repr__(self): return '<Not_A_Descriptor instance>' class Point(object): __slots__ = (()) x = Descriptor() y = Not_A_Descriptor() # # Copied from https://docs.python.org/3/howto/descriptor.html # def __getattribute__(self, key): "Emulate type_getattro() in Objects/typeobject.c" v = object.__getattribute__(self, key) if hasattr(v, '__get__'): return v.__get__(None, self) return v # # My fixed version # def fixed__Type__getattribute(self, key): "FIXED: Emulate type_getattro() in Objects/typeobject.c" v = object.__getattribute__(self, key) if any('__get__' in m.__dict__ for m in type(v).__mro__): return v.__get__(None, self) return v print('Point.x: %s' % Point.x) print('Point.y: %s' % Point.y) print("type.__getattribute__(Point, 'x'): %s" % type.__getattribute__(Point, 'x')) print("type.__getattribute__(Point, 'y'): %s" % type.__getattribute__(Point, 'y')) print("__getattribute__(Point, 'x'): %s" % __getattribute__(Point, 'x')) print("__getattribute__(Point, 'y'): %s ***WRONG***" % __getattribute__(Point, 'y')) print("fixed__Type__getattribute(Point, 'x'): %s" % fixed__Type__getattribute(Point, 'x')) print("fixed__Type__getattribute(Point, 'y'): %s ***CORRECT***" % fixed__Type__getattribute(Point, 'y'))