What Are Class Descriptors?
Why does the following snippet not work?
class Document:
@classmethod
def noop(cls):
pass
@staticmethod
def hello():
pass
def foo(self):
pass
assert Document.foo == Document.__dict__.get('foo'), "this works"
assert Document.noop == Document.__dict__.get('noop'), "this fails"
assert Document.hello == Document.__dict__.get('hello'), "this fails"
The problem is that classmethod and staticmethod are class descriptors. When we call __getattribute__ via Document.noop, the classmethod decorator transforms the noop function to be bound to Document. However, Document.__dict__.get('foo') doesn’t evaluate classmethod and simply returns the wrapped function.