Any arguments for the decorated function are just passed to __call__(). The output is:

Inside __init__()
After decoration
Preparing to call sayHello()
Inside __call__()
sayHello arguments: say hello argument list
After self.f(*args)
After first sayHello() call
Inside __call__()
sayHello arguments: a different set of arguments
After self.f(*args)
After second sayHello() call

Notice that __init__() is the only method called to perform decoration, and __call__() is called every time you call the decorated sayHello().

Now the process of decoration calls the constructor and then immediately invokes __call__(), which can only take a single argument (the function object) and must return the decorated function object that replaces the original. Notice that __call__() is now only invoked once, during decoration, and after that the decorated function that you return from __call__() is used for the actual calls.

Although this behavior makes sense -- the constructor is now used to capture the decorator arguments, but the object __call__() can no longer be used as the decorated function call, so you must instead use __call__() to perform the decoration -- it is nonetheless surprising the first time you see it because it's acting so much differently than the no-argument case, and you must code the decorator very differently from the no-argument case.

The return value of the decorator function must be a function used to wrap the function to be decorated. That is, Python will take the returned function and call it at decoration time, passing the function to be decorated. That's why we have three levels of functions; the inner one is the actual replacement function.

Because of closures, wrapped_f() has access to the decorator arguments arg1, arg2 and arg3, without having to explicitly store them as in the class version. However, this is a case where I find "explicit is better than implicit," so even though the function version is more succinct I find the class version easier to understand and thus to modify and maintain.

Decorators with and without arguments are so different that it's quite confusing. The best way I find to think about it is that with no arguments, you're just calling a decorating function on the function. With arguments you're calling a decorator "factory" that's going to return a decorator on the function.

> You might be interested in some of the discussion over> here :> http://stackoverflow.com/questions/215689/why-python-decora> tors-rather-than-closures> > Decorators with and without arguments are so different> that it's quite confusing. The best way I find to think> about it is that with no arguments, you're just calling a> decorating function on the function. With arguments you're> calling a decorator "factory" that's going to return a> decorator on the function.

I'm not sure here is the space to elaborate on this but IMO the correct perspective on decorators needs to evolve from a simple observation about the relationship of two functions F and F1 where the function F1 can be considered as a subroutine that is called by F.

The nature of the coupling between F and F1 can be twofold: either F1 is passed to F explicitly as a parameter which requires passing around two functions F and F1 everywhere F shall be called in application code or F is a closure referring to F1 which means that the coupling is fixed. So we have either full coupling of full decoupling. Both have their costs.

In a first step a decorator we can consider a decorator as a factory function G that produces closures F depending on F1.

def G(F1): def F(*args, **kwd): ... F1(x,y,...) ... return F

The function returned when decorating F1 by G can now be considered as a fixed calling context F parametrized by F1 and reassigned to F1. But this means that we have now coupled a fixed calling context F to F1. We have succeeded in liberating F from a fixed subroutine F1 but not in liberating F1 from a fixed calling context F.

In a next step we parametrize also the calling contexts F by using arbitrary parameters a, b, c... Those become closure variables of our original decorator G:

In practice this will establish a meaningful variation of F not something completely arbitrary like binding F1 to two entirely unrelated contexts F and F' depending on some parameter(s).

So in essence a decorator is a functional design pattern that is about modularization of functions ( or callables to use a more general term prevalent in Python programming ) and adjusting the coupling of functions.

Please ignore this if you find it impertinent. I'm blaming the glass of wine I had with dinner.

I can't help but think that this explanation is over-complicated.

A decorator expression consists of an identifier and an optional, possibly empty argument list. If the identifier has an argument list - empty or not - the value referenced by the identifier is called to obtain the decorator. If the identifier does not have an argument list, the value referenced is used as-is.

Another way to say it is that, if there are parens after the identifier, then the identifier is called to return the actual decorator. If there are no parens, then the identifier is the decorator.

Another factor complicating the explanation is the class implementation of decorators. While I understand that it looks neater, I find keeping track of the object lifecycle complicates the picture a little to much. Decorators are defined in terms of callables, and the straight function implementation is a better match to that.

In summary, I think it's important to explain the distinction between the following two cases as a stepping stone to explaining how to use arguments with decorators.

> This is nit-picky, but is there any reason why you're> using camelCase for your variable and method> names instead of separating_with_underscores?

Actually, that's an important issue that I have to decide for the Python book. Aesthetically I prefer camelcasing; it feels more OO (comes from Smalltalk, I believe) while underscore separation feels like C to me.

On the other hand, Python has historically used underscores and I think PEP8 says that's coding standard.

I definitely need a consistent coding standard for the book. Of course these kinds of discussions have no way to win -- I just have to be the BDFL for the book and decide.

(One argument might be that camelcasing could appeal more to Java programmers. One could also say that camelcasing emphasizes a break between pre-Python 3 and Python 3.)

If I recall correctly, the Python standard library is moving more and more towards separating_with_underscores in Python 3.0. It still won't be perfectly PEP8 compliant, but they're making it a little closer, based on some threads I've seen on the dev mailing lists.

So I'd personally like to see more Pythonic code formatting, but I don't think very many Python programmers will care all that much. Perhaps Java programmers would care more, in which case that might be the better move.

> So I'd personally like to see more Pythonic code formatting, but I don't think very many Python programmers will care all that much.

I think instead that most Pythonistas will care a lot about consistency with the official style guide. Many projects are already migrating to the convention with underscores.I personally would not recommend a recent text book using a deprecated code style.

> Another way to say it is that, if there are parens after> the identifier, then the identifier is called to return> the actual decorator. If there are no parens, then the> identifier is the decorator.

> I think instead that most Pythonistas will care a lot> about consistency with the official style guide. Many> projects are already migrating to the convention with> underscores.

I'm not sure about that. I'm seeing more and more camelCase Python code on the web. For me personally the underscores are one of the very few official style guides that I ignore simply because I find underscores pretty hard to read and camelCase saves me one keystroke (a_b = 4 strokes, aB=3 strokes).

I gotta chime in with support for Michele Simionato's decorator module.

It preserves the function signature and it makes dealing with decorator arguments MUCH more straightforward. Otherwise, you end up with a function that returns a function that returns a function, and that's just ridiculous. Throw that on top of some metaclasses, and you're guaranteed to trap python in an elitist prison for eternity :)

Also, I think the term "decorator factories" is sometimes more helpful when talking about decorators that take arguments. Strictly speaking, the arguments don't even go to a decorator. They go to a function that then returns a decorator.

I'm giving a talk at PyWorks all about decorators, and my material is available here: http://scratch.tplus1.com/decoratortalk/. I'll be updating a few sections soon, now that 2.6 is standard and I welcome feedback.

Finally, when I read PEP8, I don't really see a hard rule about underscores vs camel-case. I see it as stating a preference. The first section emphasizes that stylistic consistency is just not that important. I tend to use camel-case for anything that starts with a upper-case letter for the first letter, like exceptions and classes, and I use underscores for everything else, but I don't really care one way or the other.

Thanks for all the links and suggestions. I've added these to "Further Reading" in the Decorators chapter.

I'm trying to sort out all the questionable and confusing issues before posting the first (very raw) version of the book. The naming issue is important because things need to be consistent throughout the book, so I'm inclined to fall back on PEP8 as much as possible.

Except, as I mentioned before, for camelcasing. As Matthew said, it seems to be a preference rather than a hard-and fast rule, and camelcasing *feels* more like OO to me, as if we are emphasizing the design here (which I want to do) and putting less focus on the C-ish nature that can be expressed in Python.

Even then, it doesn't always work. A decorator like the ``@rule()`` I'm creating for the build system is implemented as a class, but just seems like it should be lowercased because we are not focusing on its class-ness but rather its behavior as a decorator.

I think you may be seeing more camel case Python because there are more people using Python coming from Java, etc. Among people who have been programming Python for some time camel case is quite uncommon -- at least in the communities I spend time in. The only exceptions in web-related libraries that I can think of are some of the Zope things, which are simply old APIs and I don't think reflect new Zope APIs.

A few years ago when there wasn't a clear convention in Python I found it quite annoying -- half the libraries would use one style, the other half the other style, and code that mixed the two would look rather ugly. And everytime you started code you'd have to decide which set of libraries the code was more closely aligned to, so as to keep the style in sync. I'm happy that's no longer the case, and that's no longer the case because we have one accepted form: underscores. If our one accepted form had been camel case that would have been fine too. But the ambiguity is really quite annoying.

So I think you should reconsider camel case, so we can keep everyone on the same page with respect to this style issue. There's nothing more OO about one or the other, they are just two ways of laying out words. There is a historical aspect I suppose -- underscores are more dominant in C and Unix, camel case in Smalltalk and Java, and camel case with leading capital letters in Microsoft APIs. But that's just history.

> A decorator like the> ``@rule()`` I'm creating for the build system is> implemented as a class, but just seems like it should be> lowercased because we are not focusing on its class-ness> but rather its behavior as a decorator.

Whereas regular classes should be CamelCase, classes used to implement decorator should be lowercase. Perhaps this is not explicitly stated in PEP 8, but it is the Pythonic thing to do, since there are lots of precedents, like staticmethod, classmethod and property. So you are doing the right thing there. The not-so-good thing is to use camelCase for method names.