Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check condition before method call

Tags:

python

I have a class named Server which can be started and stopped. Certain methods should not be called unless the Server is started, in which case a NotConnectedException should be raised. Is there a way to call a method before every method in a class and determine if class variable _started is set to True?

I tried using a decorator, but the decorator function does not have access to the class variable. I was trying to do something like this:

class Server(object):
    _started = False
    def started(self):
        if(self._started == False):
            raise NotConnectedException

    @started
    def doServerAction(self):
       ...
like image 455
BlueVoid Avatar asked Jun 05 '12 20:06

BlueVoid


1 Answers

Remember what decorators are:

@decorate
def foo(...):
    ...

is exactly equivalent to:

def foo(...):
    ...
foo = decorate(foo)

The decorator is called on the function, so calling the first parameter self makes no sense. Also, the decorator is called on the function when it is defined, and whatever it returns is used in place of the function. So even if your started decorator didn't throw an AttributeError by trying to access the _started attribute of a function, it would then return None, making all your methods set to None, and thus not even be callable.

What you want is something like this:

import functools

def started(func):
    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
        if not self._started:
            raise ...
        else:
            return func(self, *args, **kwargs)
    return wrapper

Almost all decorators are of this form; they take a function, create a wrapper that does something "around" the received function, and then return the wrapper. The use of functools.wraps here is a convenience if you ever end up working with this code in an interactive interpreter session; it automatically updates the wrapper function with the name and docstring of the original function, which makes the decorated functions "look like" the original function a bit more.

It's irrelevant whether this is defined inside the class or not.

like image 116
Ben Avatar answered Sep 22 '22 11:09

Ben