[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