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.