user144153
user144153

Reputation: 858

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?

Upvotes: 5

Views: 3849

Answers (2)

austin-schick
austin-schick

Reputation: 1245

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.

Upvotes: 5

kadee
kadee

Reputation: 8904

If one wants to keep/use also the original my_decorator, one could create a my_decorator_property as following:

def my_decorator_property(f):
    @property
    def wrapper(self, *args, **kwargs):
        return my_decorator(f)(self, *args, **kwargs)

    return wrapper

Upvotes: 0

Related Questions