Python Descriptors with Old Classes

I tried something about this google. Why do descriptors without data work with old classes?

Documents say they should not:
" Note that descriptors are only called for new objects or style classes (those that are subclassed by object() or type() ). "

 class Descriptor(object): def __init__(self): self.x = 1 def __get__(self, obj, cls=None): return self.x class A: x = Descriptor() a = A() ax >>> 1 

Thanks.

+6
source share
1 answer

You have the right to question the documentation. I tried to browse CPython sources to find an explanation, but be warned: I am not an expert.

From my point of view, the attribute search and the __get__ descriptor occurs in instance_getattr2 (selected excerpts):

 v = class_lookup(inst->in_class, name, &klass); if (v != NULL) { f = TP_DESCR_GET(v->ob_type); if (f != NULL) { PyObject *w = f(v, (PyObject *)inst, (PyObject *)(inst->in_class)); } } 

So either I am missing something, or nothing in the implementation requires an object of a new style (which contradicts the documentation).

For the record, I tried recompiling Python to limit the descriptor call to new class class objects, but this actually caused a huge mess. In the process, I found out that the class methods themselves are implemented as descriptors: this is the mechanism used to return related or unrelated method objects depending on usage. For instance:

 >>> class A: ... def foo(): ... pass ... >>> A.foo.__get__(None, A) <unbound method A.foo> >>> A.foo.__get__(A(), A) <bound method A.foo of <__main__.A instance at 0x000000000229CC48>> 

As a result, it seems that preventing descriptor calls for object attributes or old-style classes also prevents method calls on them , at least with the implementation of CPython.

Once again, I'm not an expert, and this is the first time I'm immersed in a Python implementation, so I could have been mistaken. I requested a problem to try to clarify this.

+4
source

Source: https://habr.com/ru/post/945672/


All Articles