keflavich
keflavich

Reputation: 19245

Access a parent class' property getter from the child class

I'm attempting to set up a test for a caching tool in which the cache is based on the function object and its arguments. To do this test, I need to access the exact function being called in my property, and I can't figure out how to do this.

The caching code looks like this:

def cached(func):
    """
    Decorator to cache function calls
    """

    @wraps(func)
    def wrapper(self, *args):
        # The cache lives in the instance so that it gets garbage collected
        if (func, args) not in self._cache:
            self._cache[(func, args)] = func(self, *args)
        return self._cache[(func, args)]

    return wrapper

and I have a cached property:

class SpatialMixin(object):
    @property
    @cached
    def longitude_extrema(self):
        return 25

The class looks something like this:

class MainClass(SomeOtherBaseClass,SpatialMixin):
    pass

MyObject = MainClass()

I can access base_class.SpatialMixin.longitude_extrema.fget directly, but this is a different object than MyObject.longitude_extrema.fget (which I'm using to indicate the getter of that property; you can't access it this way because MyObject.longitude_extrema is just the number 25).

So, how can I access the function underlying the MyObject.longitude_extrema property?

Upvotes: 0

Views: 264

Answers (1)

user2357112
user2357112

Reputation: 282198

If you're trying to access the original longitude_extrema function, you're not finding it through fget because the original longitude_extrema function isn't the getter. The wrapper function created in the cached decorator is the getter.

On Python 3.4+, a wrapper decorated with functools.wraps has a __wrapped__ attribute pointing to the function it wraps. You can use that to access the original longitude_extrema. (This attribute also exists on 3.2 and 3.3, but with slightly buggy behavior.)

On Python 2, functools.wraps doesn't set __wrapped__. While it's technically possible to get at the wrapped function anyway with direct closure manipulation, it's awkward, variable-name-dependent, and not a good option, especially since you control the decorator. You could just set __wrapped__ yourself in the cached decorator.

Upvotes: 1

Related Questions