Yet another PEP318
Pierre-Frédéric Caillaud
peufeu at free.fr
Fri Aug 13 02:47:30 EDT 2004
Proposal :
Make def an expression (always returns the function):
# this one behaves as usual
def funcname(params):
function body
# this one is new
# it allows us to name a function (func.__name__ ?) and also use it in
expressions
variable = def funcname(params):
function body
# or
variable = def (params):
function body
# or
return def funcname(params):
function body
Now we could write :
funcname = classmethod(
def funcname( params ):
body
)
But it looks lispish and introduces a lot of confusing parentheses...
Now, I propose (oops) a new operator, whatever name it has, which means
"the value of the expression on the next line of code". Let's say this is
a new use for "*" :
a = function1( x,*,z )
function2( f,g,h )
This would be translated by the compiler as
a = function1( x,function2( f,g,h ),z )
So we can have :
funcname = decorator1(*)
decorator2(*, other params)
def funcname( params ):
function body
What do you think ?
Yet another proposition :
execute:
funcname = classmethod( funcname )
after:
def funcname(params):
body
On Thu, 12 Aug 2004 12:33:50 -0400, Roy Smith <roy at panix.com> wrote:
> Arthur <ajsiegel at optonline.com> wrote:
>> I must say that after days of waffling, and I think an honest effort
>> to accept where things were going, I woke this morning hating
>> @decorator.
>>
>> The existing syntax for this kind of transformation is, in fact,
>> exactly what one would expect:
>>
>> foo=staticmathed(foo).
>>
>> That is the universal langauge for transformations. And when we try
>> to explain to anybody what it is that @decorator means, we go back to
>> the pseudo code that is in fact the existing syntax.
>
> I'm with Arthur.
>
> I think the core problem is that the def statement is kind of wierd. It
> does two different things. First, it creates a function body, then it
> binds the function to a name.
>
> One of the objections to:
>
> def foo ():
> whatever
> foo = decorator (foo)
>
> is that you have to type the word "foo" three times. It's not so much
> the effort of repeating the keystrokes, but the fact that it feels so
> unfactored. The only reason you need to do this is because you have no
> way of getting at the newly-generated function (what CS types would call
> a "lambda form") before it's bound to the name.
>
> A solution to that is to factor out the function definition from the
> name binding, so you would do something like:
>
> foo = def ():
> whatever
>
> although by the time you do that, you might as well have just gotten rid
> of def and used lambda() directly. If you wanted it to be a
> static/class method, you would do:
>
> foo = staticmethod_def ():
> whatever
>
> The other big objection to the current syntax is that it puts the
> wrapper way down at the bottom of the function body, away from the name.
> The above syntax solves that too.
>
> The big problem with the above is that it changes the semantics of the
> def statement in a way which is incompatible with current usage, and
> thus I would expect it's a complete non-starter. Not to mention
> inventing new keywords.
>
> On the other hand, doing:
>
> def (staticmethod) foo ():
> whatever
>
> (you can pick whatever bits of punctuation turn you on) seems like it
> should work just fine. I think it achieves all the goals:
>
> 1) It puts the decorator before the function body.
>
> 2) It keeps the decorator right next to the function name.
>
> 3) It doesn't re-define any currently valid syntax.
>
> 4) It looks enough like current Python syntax that most add-on tools
> should handle it just fine.
>
> 5) If you've got lots of decorators (I'm still not sure if people really
> think this will happen in real life), it's easy enough to break it up
> into multiple lines:
>
> def @decorator1 \
> @decorator2 \
> @decorator3 foo (a, b, c):
> print a, b, c
>
> but I'm assuming that will be the exception, just like really long
> argument lists are the exception. Define the order of application of
> multiple decorators in whichever way floats your boat; I'm guessing
> outside-in (i.e. the last one gets done first) makes the most sense.
>
> I suppose you could take this one step further and put the decorators
> inside ()'s, so you'd have any of (as auto-indented by emacs):
>
> def (decorator) foo (a, b, c):
> pass
>
> def (decorator1, decorator2, decorator3) foo (a, b, c):
> pass
>
> def (decorator1,
> decorator2,
> decorator3) foo (a, b, c):
> pass
>
> def (decorator1,
> decorator2,
> decorator3) foo (a,
> b,
> c):
> pass
>
> with the last example being a bit ugly, but at least it seems to follow
> the expected indenting rules. In any case, you'd only have to resort to
> something like that if you had lots of decorators and lots of arguments,
> and in that case, I suspect you might want to be refactoring things to
> simplify it all anyway.
>
> I haven't done an exhaustive search of all the proposed syntaxen which
> have come flying by here in the past week or so. My apologies if I've
> accidentally duplicated somebody else's work here.
>
> In retrospect (this has been written in dribs and drabs over the past
> several hours, as I've been called away repeatedly to do real work), I
> see I started out by agreeing with Arthur that the current (i.e. pre
> PEP-318) way of doing things is good enough, then managed to head off
> into a different direction and suggest YADS (Yet Another Decorator
> Syntax). Oh, well.
>
> I'm also not at all convinced that using decorators for things like doc
> strings makes any sense at all. It's just the wrong tool. Docstrings
> work just fine the way they are. If it ain't broke, don't fix it.
> Which I guess brings me full-circle back to agreeing with Arthur :-)
More information about the Python-list
mailing list