@Decorators and Property() with Python

What are they

Decorators are syntatic sugar to wrap functions

def doHardWork():
    print 'Do hard work'


def myDecorator(function):

    def wrapper():
        print 'Wake up'
        function()
        print 'Go to sleep'

    return wrapper


doHardWork = myDecorator(doHardWork)
doHardWork()

so that instead of

doHardWork = myDecorator(doHardWork)
doHardWork()

we can write

@myDecorator
def doHardWork

which is much prettier.

What are they good for

Decorators are convenient for factoring out common prologue, epilogue, and/or exception-handling code in similar functions. Besides the obvious @login_required, other nice decorators are:

Timing a function

def timing_function(some_function):
    def wrapper():
        t1 = time.time()
        some_function()
        t2 = time.time()
        return "str((t2-t1)) + "\n"
    return wrapper

Debugging functions

def debug(fn):

    def wrapper(*args):
        result = fn(*args)
        print '{0}{1} : {2}'.format(fn.__name__, args, result)
        return result

    return wrapper


@debug
def doHardWork(someArg):
    if type(someArg) is int:
        return 'int'
    elif type(someArg) is str:
        return 'str'
    else:
        return 'other'

doHardWork([])

Interesting discussion here: http://www.quora.com/What-are-common-uses-of-Python-decorators

Property() and decorators

Property() is a built in wrapper function that attaches some code to the member attribute access. It’s the Python way to deal without C++ getters/setters.

In this example I create a new member variable title, and I attach the two custom functions to get and set for that member. Throughout the class, code>_title is underscored to mean that it shouldn’t be accessed from outside the class.

class Book():
    def __init__(self):
        self._title = ''

    def get_title(self):
        if self._title == '':
            return 'title not set'
        else:
            return self._title

    def set_title(self, title):
        if len(title) < 2:
            raise ValueError('Too short')
        self._title = title
        return self._title

    # property() attaches some code to the member
    # attribute access, in this case 'title'.
    #
    # the property() signature is:
    # property(fget=None, fset=None, fdel=None, doc=None)

    title = property(get_title, set_title)


b = Book()
print(b.title)

b.title = 'moby dick'
print(b.title)

The whole example just screams for decorators :)
Also note that in Python, a method is a function that is stored as a class attribute, so it makes perfect sense that title here is a method whereas in the previous example it was an attribute.

class Book():
    def __init__(self):
        self._title = ''

    # this is the same as
    # title = property(title)
    @property
    def title(self):
        if self._title == '':
            return 'title not set'
        else:
            return self._title

    # returns a new property that inherits everything from
    # the old title(), plus it adds a setter
    @title.setter
    def title(self, title):
        if len(title) < 2:
            raise ValueError('Too short')
        self._title = title
        return self._title

b = Book()
print(b.title)

b.title = 'moby dick'
print(b.title)