[Python-Dev] Re: A syntax for function attributes?

Paul Moore pf_moore@yahoo.co.uk
Thu, 31 Jul 2003 19:58:40 +0100


"Phillip J. Eby" <pje@telecommunity.com> writes:

> I agree with the need to put information about a method near the
> definition, but I don't think that we need a separate syntax
> specifically for function attributes.  I think that with PEP 318 or
> some variant thereof, it is trivial to create an 'attrs(foo=bar,
> baz=spam)' function that can be used as a decorator, eg. in
> conjunction with classmethod.

To be honest, the *only* serious reason for any of this syntax (PEP
318, something for attributes, whatever) is to keep metadata near the
definition (or at least, the def statement, rather than after the
code...)

I like Michael Hudson's variation on PEP 318,

    def f() [mod1, mod2]:
        pass

It's minimal, flexible, and has an implementation.

The downsides that I see are:

1. It doesn't help with properties. To be honest, I don't see this as
   much of an issue, as properties are a very different beast (they
   effectively combine multiple functions in one). People have
   demonstrated clever hacks to make properties possible, which leads
   me nicely to...

2. It's possibly *too* flexible. The temptation to define clever hacks
   may be just a little high. The example of attrs() mentioned above
   is a good example. It satisfies a real need, it's simple, and it's
   easy to implement via the [...] syntax. But is it really the best
   way of handling function attributes? I really don't know, without
   trying it out. And that leads me onto...

3. It's almost impossible to tell whether it will look right in
   practice, without implementing it and trying it out. And once that
   happens, it'll probably never get removed, even if it's *not* the
   right answer.

The canonical function modifier is classmethod (or staticmethod), and
for that, Michael's syntax

    def f(...) [classmethod]:
        pass

looks great.

My canonical case for function attributes comes from the parser Spark,
which (mis-)uses docstrings to contain the grammar rule for which the
function is an action:

    def p_expr_term(self, args):
        '''
            expr ::= expr + term
            term ::= term * factor
        '''
        return AST(type=args[1],
                   left=args[0],
                   right=args[2])


To me, this certainly *isn't* going to work with something like
attrs() - imagine

    def p_expr_term(self, args) [attrs(
        rule='''
            expr ::= expr + term
            term ::= term * factor
        ''')]:
        return AST(type=args[1],
                   left=args[0],
                   right=args[2])

Yuk.

The current function attribute syntax

    def p_expr_term(self, args):
        return AST(type=args[1],
                   left=args[0],
                   right=args[2])

    p_expr_term.rule = '''
            expr ::= expr + term
            term ::= term * factor
        '''

looks better than that, IMHO.

I'm sorry, this rambled on a bit. I think that, in summary, my points
are:

    * My preferred solution for PEP 318 is Michael Hudson's patch.
    * It may be too general, in tempting people to mis-use the feature
      in inappropriate ways (but what the heck, anything can be
      misused, at some level).
    * I don't think there's an obvious solution for function
      attributes yet.
    * I think properties are another unsolved problem.

It's also interesting to note that classmethod/staticmethod and
properties get used in spite of the lack of syntactic support, whereas
function attributes generally don't seem to. I'm not quite sure what
this implies about the usefulness of function attributes...

Hope this was useful,
Paul
-- 
This signature intentionally left blank