[Python-Dev] Re: decorators and 2.4

Jeff Bone jbone at place.org
Mon Jun 28 12:50:45 EDT 2004


> Just one more opinion here, but I'm with Bob on this one. Sure, many
> of the uses I envision are "declarative" in the sense that they just
> associate metadata with the function. But many other uses I envision
> would alter the function's behavior.

I'm really curious what these uses might be.  Folks keep saying this 
kind of thing, but when you dig in IMHO most of these actually seem to 
be design-time things, statements *about* the intent or use of the 
function (relative to the language runtime itself, e.g. classmethod and 
so forth, or relative to a framework, such as registering a function, 
or relative to some tool, e.g. for extended documentation purposes or 
type-checking, etc.) rather than e.g. runtime modifications to its 
behavior.

I wouldn't keep pushing on this except that I'm entirely puzzled about 
what these legitimate "runtime" applications might be that aren't 
already more easily and clearly accomplished with existing mechanisms:  
arguments, lexical scope, and higher-order functions.  I'm all for 
decorations as a mechanism for declaring things *about* the function as 
above, but I'm at a loss re: rationale for "decorations" that do more 
than declaratively and immutably *decorate* the function.

Given that my distinctions between declarative and imperative uses of 
decorators and design- vs. run-time seem to have confused more than 
they've illuminated, perhaps a series of questions, scenarios, and 
thoughts might help clarify the areas of my concern.

(1)  Does a function have access to its own decorators?

I expect the answer here should be "yes."  We should be careful, 
though, that this does not introduce a mutable container for state.  
We've already got one such thing:  object instances.  We don't need 
another.

(2)  Do decorators define literal constant values at design-time or do 
they define a scope of mutable bindings?

The PEP gives this example:

	def mymethod(f) [attrs(versionadded="2.2", author="Guido van Rossum")]:
	    ...

That seems fine, but what about this:

	x = "Guido van Rossum"
	def mymethod(f) [attrs(versionadded="2.2", author=x)]:

Danger, Will Robinson!  ;-)  Even worse:

	x = "Guido van Rossum"
	def mymethod(f) [attrs(versionadded="2.2", author=x)]:
                    oldAuthor = someHandleToMyDecorators.atts.author
		someHandleToMyDecorators.atts.author = "Eric Idle"

IMHO, the RHS of an "assignment" in a decorator should only be some 
value that can be known at "compile" time, which probably means it's 
either a reference to a singly-assigned constant value or a literal.  
If you allow arbitrary variables or attributes in decorators to be 
assigned, then you limit the utility of decorators for many of their 
intended purposes such as e.g. type-checking.  Furthermore, if you can 
"assign" a decorator's attribute more than once --- particularly if the 
decorated thing (function, method, object, whatever) can access those 
bindings --- then you've simply re-invented objects with an alternate 
and idiosyncratic syntax.

(3)  Should it be possible to conditionally evaluate decorators based 
on run-time state?

The following, IMHO, is truly scary and inhibits many of the intended 
uses of decorators.  This shouldn't be legal, ever:

if foo = 3:
	[someDecoratorThatModifiesBarsRuntimeBehavior]
else:
	[someOtherDecorator]
def bar(...):
	...

If you're going to do that, just use callables, nested scopes, 
first-order functions, currying, etc.

jb




More information about the Python-Dev mailing list