[Tutor] Decorators: Are they good for checking inputs and outputs?

Steven D'Aprano steve at pearwood.info
Mon Jan 7 12:34:01 CET 2013


On 06/01/13 23:30, DoanVietTrungAtGmail wrote:
> Dear tutors
>
> After much reading and head-scratching, I think the basic idea of
> decorators has now clicked for me. I am a beginner in programming and in
> Python, but I want to eventually develop a serious system. To spend most of
> my time on developing the ideas and building the code, I need to test my
> code fairly well but spend as little time doing so as possible. Therefore,
> I am looking ahead and thinking of using decorators extensively.
>
> Specifically, for every function I will write, I don't want to have to
> write code to check that arguments passed to it are of the permitted
> number, type, and range, then code to deal with those errors that can be
> dealt with. This is what I hope: Once I have collected or written all the
> necessary decorators, from then on I'll just routinely decorate each
> function with a whole bunch of decorators relevant to it.


That is one use of decorators. It is not the only use.

To really understand decorators well, you have to understand the idea of
*higher order functions*. Most people get to understand the idea of a
function: you pass some arguments, and it returns a result:

def plus1(a):
     return a + 1

def plus2(a):
     return a + 2

def plus3(a):  # this is getting tedious...
     return a + 3


Higher order functions take that one step higher: instead of returning a
result (a number, a string, some other value) they return a function!

def plus_factory(value):
     # Create an inner function.
     def plus(a):
         return a + value  # value comes from the outer function
     # Change the name of the inner function, so it looks nicer.
     plus.__name__ = "plus%d" % value  # plus1, plus2, ... plus999
     # Return the inner function.
     return plus

Now I can do:

plus4 = plus_factory(4)
plus100 = plus_factory(100)
plus_a_lot = plus_factory(1234567890)


print plus4(16)  # prints 20
print plus100(16)  # prints 116


So now we have seen 1st order functions, which take simple arguments
like numbers or strings and return a new number or string, and 2nd
order functions, which take a simple argument and returns a function.
Now we look at 3rd order functions that take a function as an argument
and return a new function!


def noisy_function(func):
     name = func.__name__
     def inner(x):
         print "calling function %s with argument %r" % (name, x)
         return func(x)
     return inner


Now I can do this:


plus4 = noisy_function(plus4)

print plus4(16)

If I haven't make any mistakes, this will print two lines:

calling function plus4 with argument 16
20


Decorators are a way of easily using 3rd order functions. There are
many, many different uses for them.


> However, it seems not many people think like I do. In the discussions I
> have read on StackOverflow and elsewhere, few people use decorators for the
> above purposes, and those who do, don't seem to do it extensively. If
> decorators are truly as useful as I think they are for the above purposes,
> surely they would be used more enthusiastically, more extensively, by many
> more people.

This is Python. We're not really keen on unnecessary type checking. There are
better, or at least different, ways of getting the same effect.


> So, my first question to the tutors is: Am I giving decorators undeservedly
> high expectations for the above purposes (ie. checking inputs&  outputs,
> and dealing with some problems therein)? Are there perhaps traps down the
> line, invisible to me at the moment, which make decorators not as useful as
> I hope?

Decorators are awesome!

But using decorators for type checking, meh. That's sometimes useful, but more
often it is just limiting and annoying. This is Python, not C, and it is best
to learn Python styles of coding rather that trying to write C or Java in
Python.


> Second, if decorators are actually suitable for the above purposes, then
> where can I find repositories of decorators? (I am aware of
> the PythonDecoratorLibrary - PythonInfo Wiki, the link is not working now,
> but did a few days ago)

I'm not aware of any specialist "decorator libraries", but many, many libraries
include their own decorators which they use for their own purposes.


-- 
Steven


More information about the Tutor mailing list