In my post yesterday on generic functions, I mentioned that you could use PyProtocols’ new decorators in Python 2.2 and 2.3 as well as 2.4, by using an alternative syntax.
What I neglected to mention, however, was that this works only for PyProtocols’ “magic” decorators, that are specifically designed for this purpose. So, I got some comments from folks who were trying to use other decorators in 2.2 and 2.3, and of course it wasn’t working for them. So, here are a couple of tricks you can use, if you’d like to use decorator syntax in Python 2.2 or 2.3:
-
Use
dispatch.as()
from the CVS version of PyProtocols, as in:import dispatch class Foo(object): [dispatch.as(classmethod)] def something(cls, etc): """This will be a classmethod"""
You can pass multiple decorators to
dispatch.as()
, and they will be executed in the same order as they are for 2.4 decorators (i.e. rightmost-first). -
Or, you can use
protocols.advice.add_assignment_advisor()
to implement your own “magic” decorators. Despite the intimidating name, all you need to know is how to write a simple callback, not unlike a standard 2.4 decorator. Here’s the source of dispatch.as(), showing a simple callback implementation:def as(*decorators): """Use Python 2.4 decorators w/Python 2.2+""" if len(decorators)>1: decorators = list(decorators) decorators.reverse() def callback(frame,name,value,old_locals): for d in decorators: value = d(value) return value return add_assignment_advisor(callback)
Essentially, you just create a callback function that does the real work of the decorator. For simple decorators, you only need the
value
parameter in the callback, which is the object being decorated. More sophisticated decorators can use theold_locals
parameter to get access to a previous definition of the named object. Note, however, that your callback should always use the supplied frame and/or old_locals in place of attempting to usesys._getframe()
directly; this is because the frame your callback is actually invoked from can vary, depending on whether 2.4 ‘@’ syntax is in use.add_assignment_advisor()
hides this difference from you by making sure you get a reference to the frame where the function definition is occurring, regardless of which syntax is in use.
Finally, it’s important to note that these “magic” decorators use a very sneaky hack: they abuse the sys.settrace()
debugger hook to track whether assignments are taking place. Guido takes a very dim view of this, but the hook’s existing functionality isn’t going to change in 2.2, 2.3, or 2.4, so don’t worry about it too much. This is really a trick to get “early access” to decorators, and the 2.4 lifecycle will be plenty long enough to get our code switched over to 2.4 syntax. Somewhere around Python 2.5 or 2.6, add_assignment_advisor()
can drop the magic part and just be a backward compatibility wrapper for the decorators that use it.
Oh, and one more thing… you don’t need to install PyProtocols to use add_assignment_advisor()
, as it doesn’t depend on anything else in PyProtocols. You can just swipe that one function and copy it into your own project.
Way cool. I just wanted to ask about this 😉
— Thomas Heller
This comment has been removed by a blog administrator.
This comment has been removed by a blog administrator.