hi there Serdar Yegulalp here from InfoWorld at IDG.
today in smart python i'm going to demonstrate python decorators a way to
transform the behavior of python functions by wrapping them in other
functions or as we say decorating them decorators
give you a way to change the behaviors of functions
in a centralized fashion if you have 20 functions wrapped with a particular
decorator you can change the behavior of all of those functions at once just by
changing the decorator this is really useful in cases where for
instance you want to make sure whole groups of functions have
consistent identical behaviors now because decorators are the kinds of
things better demonstrated than talked about let's start with a few simple
examples here we have a function that does
something extremely simple all it does is it takes in a name
and prints hello using that name nothing special going on there
now let's look at the most primitive example possible of a decorator that
would work with this function a decorator is itself a function and
what it does is it takes in the function object when
it's defined in your program perform some transformation on it and
return it a decorator function always has the
function that's decorating past to it as the first argument in this case funk
all we're doing with this decorator is taking in the function we're decorating
and returning it intact and as you can see
the function still behaves the same exact way
now let's look at a decorator that actually modifies the function behavior
this is where things get a little more complex
now this new decorator does three things first
it takes in the original function as funk again
and then generates on the fly a new function to replace it
one which wraps the old one hence the name of the function
wrapper although the choice of name is pretty much arbitrary
you see how we have a call to func in the middle of wrapper the idea there is
that we're intercepting the calls to the original function
we're transforming them in some way and then passing along the transformed calls
back to the original in this particular case we're taking the
name argument we're adding mister to the front of it
and passing it along to the original say hi function
notice here that rapper will take in arbitrary arguments through the star a
and the double star ka arguments many wrapper functions do this sort of
thing as a way to ensure maximum compatibility with whatever it is
they're wrapping they just want to pass the arguments
along as is now in this case we're really only interested in the first
argument which is a0 if we're wrapping functions where we
know the arguments we can simplify this just by using the actual argument names
and we'll see an example of that in a little bit
also there's nothing that says we have to modify any of the arguments that's
just one of the possibilities available to us
when we use a decorator finally the third thing we do we return the new
wrapper function so that it is substituted for the
original all of this by the way is an example of
how in python functions are first class objects they can be created at
runtime like any other kind of object so all we're doing here is creating at
runtime one function as a substitute for another
the decorator syntax just automates this process
now let's have a look at a concrete use case for a decorator
let's say you have an application that works with a database and you want to
automate the process of only allowing users with admin permissions to work
with certain functions here in this example we have a function
accessdb that takes in a username but there's no validation logic for the
user in the function itself it's all in the decorator the
decorator function takes in the username checks it and if
it's ad bin only then does it run the decorated
function and return the results from it if there's no match it throws a custom
exception at bottom when we run the function
against multiple names you'll see that only admin runs successfully
again the key thing here is how all the validation logic is in the decorator not
the function itself if we have a hundred functions that need custom validation
logic like this then we can just push them all off into a decorator
and there have this single central place to handle it
and to make it a syntactically elegant way to allow our functions to use it
we could have for instance a validation function in line at the beginning of
every single one of those functions but that generates a lot of boilerplate
it looks ugly it gets cluttered finally decorators can be nested in this
example here we have two decorators one that
transforms the name into upper case and another that adds mr before it in
the first example it performs up case first and then adds
mister the second example adds mister first and then performs up case
you'll notice that the order of the behavior
is the same as the order that decorators appear in
the top most decorator is the outermost wrapper the one below it the next
outermost and so on until we get to the creamy function center within
the important thing to understand is that each wrapped function is itself
just another function so we can wrap them indefinitely as long as we
make sure that we're still passing the arguments along consistently from one to
the next that's it for this overview of
decorators if you liked it leave a comment below
don't forget to subscribe to the idg tech talk channel on youtube and for
more smart python follow us on facebook youtube and
infoworld.com