Search code examples
pythondecoratorpython-decorators

Custom property decorator that behaves like @property?


I'd like to create a custom Python decorator that will 1) check the value of a class attribute my_attribute before running the function, and 2) turn the class method into a property. I can achieve this as follows:

def my_decorator(f):
    def wrapper(self, *args, **kwargs):
        if self.my_attribute is None:
            raise ValueError('No location set to model.')

        return f(self, *args, **kwargs)
    return wrapper

class MyClass:
    my_attribute = None

    @property
    @my_decorator
    def my_method():
        return self. my_attribute

I'd like to know how I can edit the definition of my_decorator so that it makes the wrapped method a property. Essentially I'd like to avoid the use of @property and @my_decorator for each method, letting me write the class definition as

class MyClass:
    my_attribute = None

    @my_new_decorator
    def my_method():
        return self. my_attribute

I've looked up the declaration of the builtin @property decorator, but it's defined as a class and wasn't much help.

Any suggestions?


Solution

  • What if you changed your decorator definition to look like this?

    def my_decorator(f):
        @property
        def wrapper(self, *args, **kwargs):
            if self.my_attribute is None:
                raise ValueError('No location set to model.')
    
            return f(self, *args, **kwargs)
        return wrapper
    

    That should make the returned function behave like a property, and keep your custom error handling.