[Python-Dev] def ... decorate

Josiah Carlson jcarlson at uci.edu
Fri Aug 13 21:13:55 CEST 2004


On Fri, 13 Aug 2004 21:27:23 +0400 (MSD)
Roman Suzi <rnd at onego.ru> wrote:

> >>  + doesn't surprise Python programmer, because it is like try-except, etc
> >
> >It surprises anyone who expects the function signature immediately after
> >the name.
> 
> I do disagree. In my suggestion function is being defined in natural order
> hich is illustratable by use of lambda:
> 
> 
> f =                               \
>   decor(                          \
>     lambda arg:                   \
>       return_val)
> 
> Decorators could be destructive and change function completely, so it's
> pitiful signature doesn't mean much.

That is funny, because in the 100,000+ lines of Python I've written over
the years, function signatures are, in fact, important.  Knowing a
signature allows you to call a function, and I believe that any
decorator that destroys a signature willingly should be considered
broken.

One could make the claim that function signatures are at least as
important as the function body; if you don't know how to call a function,
then its body is nearly worthless.  Interestingly enough, decorators are
important to PyObjC developers because they use decorators to specify
signatures.

As for the "natural order" of definitions, in Python, the natural order
of definitions uses 'def', 'lambda' is considered by many (Guido
included) to be a mistake.  I believe your argument using lambda is poor.


> >>  + reads a natural language (with implicit "with"  after "f")
> >
> >But it is so radically different from current definitions that it breaks
> >current understanding about the language.
> 
> Why? IMHO @s are much more radical.

Seemingly in Guido's opinion, @s (or other symbols) were minimal.  You
can have a humble (or not so humble) opinion, but unless you can
convince Guido and/or the community, it is not going to happen (I've
been bitten by this myself).


> >It also requires people to
> >learn two significantly different semantics for defining a function.
> 
> No more "significantly different" than learning
> 
> import m
> 
> and
> 
> from m import something

While the use of 'from' implies something has changed in imports, and it
would imply something has changed in the decorator syntax, the use of
from differs.  Also, with your proposed decorator syntax, one inserts
'from' into the middle of the defintion of the function with decorators,
basically making 'from' into noise.


> >The good proposals (IMO) keep the function name and signature unchanged.
> >
> >So let us read this "natural language" (my interpretation of the syntax
> >given above):
> >
> >define f as a staticmethod... from the arguments self and p with
> >function body...  Not bad, though I don't like the visual aesthetics.
> 
> Ok. Now I see our disagrement. I am thinking in terms of
> applying decorators to make some other function FROM
> a given function while you are reasoning about "adding" attributes to the
> defined function.

No, our disagreement isn't about how we understand decorators.  I never
argue it is about adding attributes, as I have actually read the 1800+
postings on decorators in the last 8 months, where attributes are
basically stated as being not arguable.


Our disagreement is about what is a reasonable decorator syntax.  I
don't believe that anything that changes the look of a function
signature to be a reasonable decorator syntax.


> >>  + doesn't require any new keywords or symbols and "prefix" operators
> >
> >Prefix operators don't seem that bad to me, nor to Guido (who offered
> >them in the first place), nor to the dozen+ others who have stated that
> >"@, !, %, *, -, +, | or & is cool".
> 
> (ooops! I mean "prefix statements" - statements sticking to
> other statements, modifying their semantics)

What, like the following?

decorate(memoize)
def fun(arg):
    #body

I think the fact that the above is actually implemented suggests that it
makes sense for many people.  Some have even stated "Just stick it in
the standard library and call it good."  If it didn't rely on
implementation-specific CPython hooks, I believe that Guido would have
preferred it to '@'.


> >As for keywords, there has been an offered solution; the use of a future
> >import.  Similar to the way yield was used in 2.3.
> 
> IMO, decorators deserve no keywords...

I wouldn't say anything of the sort.  I don't believe keywords are
/necessary/ for decorators, but if a new keyword makes it click for
Guido (very unlikely), then so be it.


> >>From is an import semantic, not function definition.  Overloading 'from'
> >does remove the necessity of a new keyword, but so does the use of the
> >symbols previously offered.
> 
> I see no problem overloading preposition like "from", "as", "to", etc,
> if it adds natural readability to language statements.

Ahh, you seem to have missed that neither "as" nor "to" are keywords:

>>> def as(arg):
...     print "as", arg
...
>>> as(1)
as 1
>>> def to(arg):
...     print "to", arg
...
>>> to(1)
to 1


Personally, I have no issue with keyword reuse, as long as they make
sense.  Considering the logical separation of the use of from during
imports, and your use of from, I think it could confuse new users of the
language.


> >>  + is explicit about transformation
> >>  + no additional indentation
> >
> >Ahh, but you indent the block of decorators before the function
> >definition must /always/ be read in order to figure out . While this has
> >been done before (try, except, finally)
> 
> I mean "no additional" level, like other group decoration proposals.

Oops, I didn't finish my argument.

I know what you meant.  In order to understand what a function does, one
must read the decorators.  While associated indented blocks have been
done before (try, except, finally, else), one doesn't need to read the
try block to understand that if an exception were to occur, the except
block would be executed.  In order to understand the semantics of a
function definition, you need to read the decorators.  Having an
indented block previous to the function definition, which includes the
decorators for the function below, only makes sense if the name is given
before the decorators (the brain-stack argument).  However, since the
function signature is as important as any decorator, then the signature
should be prominant.

I believe your arguments are better focused toward a different syntax,
namely:

def fun(args):
    @deco
    #body

I think it beats your offered syntax hands-down due to its conciseness
and lack of need to include a separate indented block for decorations. 
It also doesn't require re-learning the meaning of "from".


> However, I am not sure Guido will change his mind and replace
> '@' with something else. Probably, Python became too boring without
> fresh syntax solutions like pies.

Guido has stated, quite clearly, that if we can come up with a better
symbol than "@", then he will go with it.


> If so, I'd added a possibility to use ";" to delimit decorators:

With the @ syntax, I believe it has been stated that multiple decorators
on one line is not to be supported.

 
> May double pie mean "repeat last time used pie":

Good for typing reduction, bad for understanding.  While a user can know
that the function is being decorated, the decorators are not immediately
available, nor are named.  Since we can name things, perhaps we should.
In this case, I believe copy+paste is preferable, or even named multiple
application of decorators.

def multi_decorate(*decorators):
    def decorate(function):
        a = decorators[:]
        while a:
            function = a.pop()(function)
        return function
    return decorate


my_deco = multi_decorate(staticmethod, returns(int))

@my_deco
def foo(args):
    #body

@my_deco
def goo(args):
    #body


 - Josiah



More information about the Python-Dev mailing list