Home > other >  Why do instance variables and class variables return different output for this closure?
Why do instance variables and class variables return different output for this closure?

Time:10-21

I have a closure that is supposed to save the return value of a computationally heavy function for reuse. However, when I run the exact same line of code (_ = cached_readonly_property(lambda: "b")), I get different return values based on whether the variable is a class variable (b) or instance variable (c). Why is this the case? Is there a way to have self.a return "a" just as self.b returns "b"?

def cached_readonly_property(return_callable: Callable):
    cached_value = None

    @property
    def prop(self):
        nonlocal cached_value
        if cached_value is None:
            cached_value = return_callable()
        return cached_value

    return prop

class A:
    b = cached_readonly_property(lambda: "b")
    def __init__(self) -> None:
        self.a = cached_readonly_property(lambda: "a")
        print()

a = A()
print(a.a)
print(a.a)
print(a.b)
print(a.b)

# Outputs:
# <property object at 0x10d2106d0>
# <property object at 0x10d2106d0>
# b
# b

CodePudding user response:

Property descriptors support binding behavior only on class variables.

Python runtime transforms the class variable during attribute lookup to the following.

type(a).__dict__['b'].__get__(b, type(b))

For a attribute, you need to make a direct call to read its value.

        print(a.a.__get__(a))
  • Related