@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)