tweaking @decorator syntax

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Sandy Norton

    tweaking @decorator syntax

    If we are going to be stuck with @decorators for 2.4, then how about
    using blocks and indentation to elminate repetition and increase
    readability:


    Example 1
    ---------

    class Klass:
    def __init__(self, name):
    self.name = name

    @staticmethod
    def statmethod1(x):
    return x

    def statmethod2(y):
    return y

    @classmethod
    def classmethod1(cl s):
    return cls

    def classmethod2(cl s):
    return cls

    @funcattrs(name ='GvR', language='pytho n')
    @log(file='func .log')
    def sayhello(self):
    print 'hello python world'

    def saygoodbye(self ):
    print 'goodby python world'

    Example 2
    ---------

    class Klass:
    def __init__(self, name):
    self.name = name

    @staticmethod:
    def statmethod1(x):
    return x

    def statmethod2(y):
    return y

    @classmethod:
    def classmethod1(cl s):
    return cls

    def classmethod2(cl s):
    return cls

    @funcattrs(name ='GvR', language='pytho n'),
    log(file='func. log'):
    def sayhello(self):
    print 'hello python world'

    def saygoodbye(self ):
    print 'goodby python world'


    Perhaps, you can eliminate the '@' alltogether:

    Example 3
    ---------

    class Klass:
    def __init__(self, name):
    self.name = name

    staticmethod:
    def statmethod1(x):
    return x

    def statmethod2(y):
    return y

    classmethod:
    def classmethod1(cl s):
    return cls

    def classmethod2(cl s):
    return cls

    funcattrs(name= 'GvR', language='pytho n'),
    log(file='func. log'):
    def sayhello(self):
    print 'hello python world'

    def saygoodbye(self ):
    print 'goodby python world'


    Sandy
  • Christopher T King

    #2
    Re: tweaking @decorator syntax

    (warning, long rant follows)

    On 4 Aug 2004, Sandy Norton wrote:
    [color=blue]
    > Perhaps, you can eliminate the '@' alltogether:[/color]

    I was thinking the same thing, only using a keyword in place of '@' rather
    than dropping it entirely:

    decorate classmethod, somethingelse:
    def somefunc(self):
    pass

    I haven't seen this, or any of your proposals previously mentioned
    anywhere (which doesn't mean they haven't been considered and rejected,
    since the @ syntax was kept a good secret until it made it into 2.4a2).

    Another proposal was to use a 'using' keyword like this:

    using:
    classmethod
    somethingelse
    def somefunc(self):
    pass

    But this was shot down because (from PEP 318):

    The function definition is not nested within the using: block making it
    impossible to tell which objects following the block will be decorated.

    Okay then. Your & my syntaxes fix this problem nicely.

    Nesting the function definition within the using: block suggests
    nesting of namespaces that doesn't exist. The name foo would actually
    exist at the same scope as the using: block.

    This arguments seems to apply to our syntaxes, but... it turns out it's
    not an argument at all! 'if' doesn't nest namespaces. Neither does
    'for', 'try', 'while', etc. Only function and class definitions nest
    namespaces; I wouldn't expect anything else to.

    Finally, it would require the introduction of a new keyword.

    This would apply to my idea, but frankly, I don't see how introducing a
    new keyword in order to introduce a MAJOR language feature is any
    different that introducing the butt-ugly '@' syntax, save that it may
    cause conflicts with older code, in which case we should save decorators
    for 3.0 (which IMAO should be the case anyways).

    I'd like to continue this thread by suggesting another idea, side-stepping
    a backwards-incompatible syntax change:

    def somefunc(self):
    [classmethod, somethingelse]
    pass

    This has the following advantages:

    1) No new syntax or keywords.
    2) No nesting issues.
    3) Follows a previous precedent (docstrings).
    4) Implementable in pure Python for great backwards-compatibility
    (http://users.wpi.edu/~squirrel/temp/decorate.py for a proof-of-concept)
    5) Near the top of the function, so it is quite visible, but below the
    function name, so it doesn't take attention away from what's important.

    And the following disadvantages:

    1) No new keyword/syntax means looking at it and saying "what's that?"
    2) Will run without immediate error in older Pythons, possibly causing
    hard-to-track-down bugs.
    3) Guido won't like it.

    Of course, I prefer the nested block idea better (either with a new
    keyword or new syntax), but I don't see those (especially the syntax one)
    flying anytime soon.

    Unless someone can come up with an idea everyone can agree on Real Soon
    Now, I think the whole idea should be dropped and wait until 3.0. We'll
    have plenty of time to argue about it then.

    Sorry about the long rant, but it felt good to get that all off my chest.

    Comment

    • Sandy Norton

      #3
      Re: tweaking @decorator syntax

      On 4 Aug 2004, Christopher T King wrote:
      [color=blue]
      > Of course, I prefer the nested block idea better (either with a new
      > keyword or new syntax), but I don't see those (especially the syntax one)
      > flying anytime soon.[/color]

      I know further discussion of this topic is feeling futile, but one can only hope.
      [color=blue]
      > Unless someone can come up with an idea everyone can agree on Real Soon
      > Now, I think the whole idea should be dropped and wait until 3.0. We'll
      > have plenty of time to argue about it then.[/color]

      Agreed.
      [color=blue]
      > Sorry about the long rant, but it felt good to get that all off my chest.[/color]

      Please, we need more rants like yours. Now if they could somehow
      collectively become a 'public outcry' (-;

      I realize my hasty initial post didn't actually show the present 2.4 form,
      so I've included it and added your variations for the sake of comparison:


      Current 2.4b Syntax
      -------------------

      class Klass:
      def __init__(self, name):
      self.name = name

      @staticmethod
      def statmethod1(x):
      return x

      @staticmethod
      def statmethod2(y):
      return y

      @classmethod
      def classmethod1(cl s):
      return cls

      @classmethod
      def classmethod2(cl s):
      return cls

      @funcattrs(name ='GvR', language='pytho n')
      @log(file='func .log')
      def sayhello(self):
      print 'hello python world'

      @funcattrs(name ='GvR', language='pytho n')
      @log(file='func .log')
      def saygoodbye(self ):
      print 'goodbye python world'


      Nested Alternative 1
      --------------------

      class Klass:
      def __init__(self, name):
      self.name = name

      @staticmethod
      def statmethod1(x):
      return x

      def statmethod2(y):
      return y

      @classmethod
      def classmethod1(cl s):
      return cls

      def classmethod2(cl s):
      return cls

      @funcattrs(name ='GvR', language='pytho n')
      @log(file='func .log')
      def sayhello(self):
      print 'hello python world'

      def saygoodbye(self ):
      print 'goodbye python world'



      Nested Alternative 2
      --------------------

      class Klass:
      def __init__(self, name):
      self.name = name

      @staticmethod:
      def statmethod1(x):
      return x

      def statmethod2(y):
      return y

      @classmethod:
      def classmethod1(cl s):
      return cls

      def classmethod2(cl s):
      return cls

      @funcattrs(name ='GvR', language='pytho n'),
      log(file='func. log'):

      def sayhello(self):
      print 'hello python world'

      def saygoodbye(self ):
      print 'goodbye python world'


      Perhaps, you can eliminate the '@' alltogether. This is
      definitely my favourite as it reads the way I think:

      Nested Alternative 3
      --------------------

      class Klass:
      def __init__(self, name):
      self.name = name

      staticmethod:
      def statmethod1(x):
      return x

      def statmethod2(y):
      return y

      classmethod:
      def classmethod1(cl s):
      return cls

      def classmethod2(cl s):
      return cls

      funcattrs(name= 'GvR', language='pytho n'),
      log(file='func. log'):

      def sayhello(self):
      print 'hello python world'

      def saygoodbye(self ):
      print 'goodbye python world'

      Alternative 4 (C T King)
      ------------------------

      class Klass:
      def __init__(self, name):
      self.name = name

      decorate staticmethod:
      def statmethod1(x):
      return x

      def statmethod2(y):
      return y

      decorate classmethod:
      def classmethod1(cl s):
      return cls

      def classmethod2(cl s):
      return cls

      decorate funcattrs(name= 'GvR', language='pytho n'),
      log(file='func. log'):

      def sayhello(self):
      print 'hello python world'

      def saygoodbye(self ):
      print 'goodbye python world'

      Alternative 5 (C T King)
      ------------------------

      class Klass:
      def __init__(self, name):
      self.name = name

      def statmethod1(x):
      [staticmethod]
      return x

      def statmethod2(y):
      [staticmethod]
      return y

      def classmethod1(cl s):
      [classmethod]
      return cls

      def classmethod2(cl s):
      [classmethod]
      return cls

      def sayhello(self):
      [decorate funcattrs(name= 'GvR', language='pytho n'),
      log(file='func. log')]
      print 'hello python world'

      def saygoodbye(self ):
      [decorate funcattrs(name= 'GvR', language='pytho n'),
      log(file='func. log')]
      print 'goodbye python world'


      Methinks issues arise generally with the nested form
      in the case of:
      - v. long functions
      - using @decorators for annotating type info e.g:

      @accepts(int, str)
      @returns(str)
      def func(x, s):
      return s + str(x)

      But I didn't think that this was the purpose of introducing func
      decorators in the first place.

      Hey since we are in amateur language design mode ,
      what the heck, let's play with that problem too:

      haskell-like:

      int, str -> str
      def funct(x, s):
      return s + str(x)

      boo-like:

      def func(x as int, s as str) as str :
      return s + str(x)

      a mix:

      def func(x as int, s as str) -> str:
      return s + str(x)

      examples of excessive colonic punctuation:

      def func(x:int, s:str):
      return (s+str(x)):str

      def func(x:int, s:str):str :
      return s+str(x)

      def func str:(int:x, str:s):
      return s+str(x)

      def func(x:int, s:str):
      return (s+str(x)):str


      Sheesh... I'm feeling nauseous and dizzy now so I think I'd better stop
      before I crap on my keyboard.

      Language design land is no place for amateurs with feeble tummies.

      ciao

      Sandy

      Comment

      • John Marshall

        #4
        Re: tweaking @decorator syntax

        On Thu, 2004-08-05 at 08:41, Sandy Norton wrote:[color=blue]
        > On 4 Aug 2004, Christopher T King wrote:
        >[color=green]
        > > Of course, I prefer the nested block idea better (either with a new
        > > keyword or new syntax), but I don't see those (especially the syntax one)
        > > flying anytime soon.[/color]
        >
        > I know further discussion of this topic is feeling futile, but one can only hope.
        >[color=green]
        > > Unless someone can come up with an idea everyone can agree on Real Soon
        > > Now, I think the whole idea should be dropped and wait until 3.0. We'll
        > > have plenty of time to argue about it then.[/color]
        >
        > Agreed.
        >[color=green]
        > > Sorry about the long rant, but it felt good to get that all off my chest.[/color]
        >
        > Please, we need more rants like yours. Now if they could somehow
        > collectively become a 'public outcry' (-;
        >
        > I realize my hasty initial post didn't actually show the present 2.4 form,
        > so I've included it and added your variations for the sake of comparison:
        >[/color]

        With the current choice and the list of alternatives you gave,
        two things struck me about the location of the decorators
        in the current choice:
        1) They seem to be in the wrong place with respect to
        what they are affecting.
        2) Can decorators easily be extended to apply to class
        and module?

        Whether or not the @ or some other operator/keyword/etc. is
        used, what is more easily understandable/readable?
        -----
        class Klass:
        def __init__(self, name):
        self.name = name

        @staticmethod
        def statmethod1(x):
        return x

        @classmethod
        def classmethod1(cl s):
        return cls

        @funcattrs(name ='GvR', language='pytho n')
        @log(file='func .log')
        def sayhello(self):
        print 'hello python world'
        -----
        or
        -----
        class Klass:
        def __init__(self, name):
        self.name = name

        def statmethod1(x):
        @staticmethod

        return x

        def classmethod1(cl s):
        @classmethod

        return cls

        def sayhello(self):
        @funcattrs(name ='GvR', language='pytho n')
        @log(file='func .log')

        print 'hello python world'
        -----

        If the decorators are metadata, that may be extended to affect
        not only functions or methods, but classes, and modules(?), I would
        think that wherever a variable or function call would go that
        would affect the function, method, class, or module, is the
        right place for a decorator.

        In the alternative above, it _may_ be that the decorators would
        only be valid if they are located in specific locations, e.g.,
        before any non decorator (or comment, or __doc__ information)
        statements.

        John

        Comment

        • Bengt Richter

          #5
          Re: tweaking @decorator syntax

          On 05 Aug 2004 14:17:25 +0000, John Marshall <John.Marshall@ ec.gc.ca> wrote:
          [color=blue]
          >On Thu, 2004-08-05 at 08:41, Sandy Norton wrote:[color=green]
          >> On 4 Aug 2004, Christopher T King wrote:
          >>[color=darkred]
          >> > Of course, I prefer the nested block idea better (either with a new
          >> > keyword or new syntax), but I don't see those (especially the syntax one)
          >> > flying anytime soon.[/color]
          >>
          >> I know further discussion of this topic is feeling futile, but one can only hope.
          >>[color=darkred]
          >> > Unless someone can come up with an idea everyone can agree on Real Soon
          >> > Now, I think the whole idea should be dropped and wait until 3.0. We'll
          >> > have plenty of time to argue about it then.[/color]
          >>
          >> Agreed.
          >>[color=darkred]
          >> > Sorry about the long rant, but it felt good to get that all off my chest.[/color]
          >>
          >> Please, we need more rants like yours. Now if they could somehow
          >> collectively become a 'public outcry' (-;
          >>
          >> I realize my hasty initial post didn't actually show the present 2.4 form,
          >> so I've included it and added your variations for the sake of comparison:
          >>[/color]
          >
          >With the current choice and the list of alternatives you gave,
          >two things struck me about the location of the decorators
          >in the current choice:
          > 1) They seem to be in the wrong place with respect to
          > what they are affecting.
          > 2) Can decorators easily be extended to apply to class
          > and module?
          >
          >Whether or not the @ or some other operator/keyword/etc. is
          >used, what is more easily understandable/readable?
          >-----
          >class Klass:
          > def __init__(self, name):
          > self.name = name
          >
          > @staticmethod
          > def statmethod1(x):
          > return x
          >
          > @classmethod
          > def classmethod1(cl s):
          > return cls
          >
          > @funcattrs(name ='GvR', language='pytho n')
          > @log(file='func .log')
          > def sayhello(self):
          > print 'hello python world'
          >-----
          >or
          >-----
          >class Klass:
          > def __init__(self, name):
          > self.name = name
          >
          > def statmethod1(x):
          > @staticmethod
          >
          > return x
          >
          > def classmethod1(cl s):
          > @classmethod
          >
          > return cls
          >
          > def sayhello(self):
          > @funcattrs(name ='GvR', language='pytho n')
          > @log(file='func .log')
          >
          > print 'hello python world'
          >-----
          >
          >If the decorators are metadata, that may be extended to affect
          >not only functions or methods, but classes, and modules(?), I would
          >think that wherever a variable or function call would go that
          >would affect the function, method, class, or module, is the
          >right place for a decorator.
          >
          >In the alternative above, it _may_ be that the decorators would
          >only be valid if they are located in specific locations, e.g.,
          >before any non decorator (or comment, or __doc__ information)
          >statements.
          >[/color]

          ISTM that this "decorating " business is a lot like what __metaclass__ does
          for classes -- i.e., right at the end of a definition, the system looks for
          a function to provide an optional extension of the definition process.

          In the case of @some_name, 'some_name' is looked up somewhere (where? locals(),
          nested scopes, globals(), globals()['__builtins__'].__dict__ ?) and the value is
          supposed to be an appropriate decorator function.

          I'm thinking of an alternative that doesn't seem to have been mentioned before,
          namely a built-in class and a standard instance of it, containing a namespace which
          would be used to find decorators, and which could be overridden and specialized etc.

          Thus
          @A @B
          def foo():
          return whatever()

          might look like

          metafunctions.a dd(foo=(A, B)) # could precede def anywhere you like for coding clarity
          def foo():
          return whatever()

          and python function definition internals would be modified a la class/__metaclass__
          functionality to find A and B via metafunctions (best design TBD ;-) and call as now
          specified. Perhaps this could be unified with __metaclass__ and we could have, e.g.,
          metafunctions.a dd(MyClass=type ) # turn classic to new style

          Obviously you could define metafunctions to apply default decorators, e.g.
          metafunctions.s etdefault(A,B,C )
          metafunctions.d o_default_for(' foo bar baz'.split())
          def foo(): ...
          def bar(): ...
          etc.
          If you wanted to suppress metafunctions altogether, you could by convention shadow it
          with a local None, i.e.,
          metafunctions = None
          ...
          del metafunctions # restore visibility of builtin


          Or if you wanted a local copy to mess with in a particular module or program,
          (it would probably not be good to allow .add easily to modify the builtin itself
          unless there was a way to restore it reliably) you could perhaps write
          metafunctions = __builtins__.me tafunctions.cop y()

          or you could define your own class
          class MyMetfun(Metafu nctions):
          ...

          metafunctions = MyMetafun(...)
          metafunctions.m y_handy_method( ...)

          etc.

          The time of action might also be controlled in the future if someone finds it useful.
          I.e., the time for examples above is right at the end of the function or class definition.
          It might be interesting to be able to have metafunctions act at other times when certain
          things are recognized also. What about at the time of instantiation of an exception, e.g.,
          to inject debugging info or whatever?
          if __debug__:
          metafunctions = __import__('mym agic').Magic() #??
          metafunctions.a dd('MyException ' ...)

          You might need some way of defining patterns to recognize besides a plain name string.
          Of course, instantiation of an exception is just a special case of instantiating a class,
          so we could have metafunctions decorating object instances too, without modifying the source
          of their classes. Hm, what about decorating module instances on import?

          This and other possibilities would make possible factoring code in new ways, I suspect,
          but as I just thought of it, I haven't really thought about it any further than you see here ;-)
          Some possibilities would probably be dangerous, cryptic, and inadvisable in most circumstances.
          We already have plenty of that. IMO the question is whether ordinary usage would help make for clearer
          and more powerful expressions of coding ideas, and perhaps introduce useful elements for thinking
          up those ideas.

          I'm not for "tweaking @decorator syntax" -- I'm for saving '@' for something worthier
          of its scarce-syntax-resource status.

          Regards,
          Bengt Richter

          Comment

          • Sandy Norton

            #6
            Re: tweaking @decorator syntax

            Here are some more variations.

            Please copy/paste the code below into your favourite python editor and see
            how each syntactical variation of the decorator code reads, and how quickly
            you grok its structure and meaning.


            #----------------------------------------------------------------------
            # current syntax 2.3 syntax
            #----------------------------------------------------------------------

            class Klass:
            def __init__(self, name):
            '''class initialization
            '''
            self.name = name


            def statmethod1(x):
            '''does something to x
            '''
            return x
            statmethod1 = staticmethod(st atmethod1)

            def statmethod2(y):
            '''does something to y
            '''
            return y
            statmethod2 = staticmethod(st atmethod2)


            def clsmethod1(cls) :
            '''does something to cls
            '''
            return cls
            clsmethod1 = classmethod(cls method1)

            def clsmethod2(cls) :
            '''does something to cls
            '''
            return cls
            clsmethod2 = classmethod(cls method2)


            def go(obj):
            '''synced obj is activated
            '''
            obj.activate()
            go = synchronized(go )


            def f(x,y):
            '''tests two ints for equality
            '''
            return x == y
            f = accepts(f, (int, int))
            f = returns(f, (str))




            #----------------------------------------------------------------------
            # @decorator syntax proposed for 2.4
            #----------------------------------------------------------------------

            class Klass:
            def __init__(self, name):
            '''class initialization
            '''
            self.name = name

            @staticmethod
            def statmethod1(x):
            '''does something to x
            '''
            return x

            @staticmethod
            def statmethod2(y):
            '''does something to y
            '''
            return y

            @classmethod
            def clsmethod1(cls) :
            '''does something to cls
            '''
            return cls

            @classmethod
            def clsmethod2(cls) :
            '''does something to cls
            '''
            return cls

            @synchronized
            def go(obj):
            '''synced obj is activated
            '''
            obj.activate()

            @accepts(int, int)
            @returns(bool)
            def f(x,y):
            '''tests two ints for equality
            '''
            return x == y



            #----------------------------------------------------------------------
            # Nested, @decorator syntax proposed for 2.4
            #----------------------------------------------------------------------

            class Klass:
            def __init__(self, name):
            '''class initialization
            '''
            self.name = name

            @staticmethod
            def statmethod1(x):
            '''does something to x
            '''
            return x

            def statmethod2(y):
            '''does something to y
            '''
            return y

            @classmethod
            def clsmethod1(cls) :
            '''does something to cls
            '''
            return cls

            def clsmethod2(cls) :
            '''does something to cls
            '''
            return cls

            @synchronized
            def go(obj):
            '''synced obj is activated
            '''
            obj.activate()

            @accepts(int, int)
            @returns(bool)
            def f(x,y):
            '''tests two ints for equality
            '''
            return x == y


            #----------------------------------------------------------------------
            # Nested, minimal decorator syntax proposed for 2.4
            #----------------------------------------------------------------------

            class Klass:
            def __init__(self, name):
            '''class initialization
            '''
            self.name = name

            staticmethod:
            def statmethod1(x):
            '''does something to x
            '''
            return x

            def statmethod2(y):
            '''does something to y
            '''
            return y

            classmethod:
            def clsmethod1(cls) :
            '''does something to cls
            '''
            return cls

            def clsmethod2(cls) :
            '''does something to cls
            '''
            return cls

            synchronized:
            def go(obj):
            '''synced obj is activated
            '''
            obj.activate()

            accepts(int, int), returns(bool):
            def f(x,y):
            '''tests two ints for equality
            '''
            return x == y


            #----------------------------------------------------------------------
            # Nested, 'decorate' keyword syntax proposed for 2.4
            #----------------------------------------------------------------------

            class Klass:
            def __init__(self, name):
            '''class initialization
            '''
            self.name = name

            decorate staticmethod:
            def statmethod1(x):
            '''does something to x
            '''
            return x

            def statmethod2(y):
            '''does something to y
            '''
            return y

            decorate classmethod:
            def clsmethod1(cls) :
            '''does something to cls
            '''
            return cls

            def clsmethod2(cls) :
            '''does something to cls
            '''
            return cls

            decorate synchronized:
            def go(obj):
            '''synced obj is activated
            '''
            obj.activate()

            decorate accepts(int, int), returns(bool):
            def f(x,y):
            '''tests two ints for equality
            '''
            return x == y


            #----------------------------------------------------------------------
            # Nested, |decorator| syntax proposed for 2.4
            #----------------------------------------------------------------------

            class Klass:
            def __init__(self, name):
            '''class initialization
            '''
            self.name = name

            |staticmethod|
            def statmethod1(x):
            '''does something to x
            '''
            return x

            def statmethod2(y):
            '''does something to y
            '''
            return y

            |classmethod|
            def clsmethod1(cls) :
            '''does something to cls
            '''
            return cls

            def clsmethod2(cls) :
            '''does something to cls
            '''
            return cls

            |synchronized|
            def go(obj):
            '''synced obj is activated
            '''
            obj.activate()

            |accepts(int, int), returns(bool)|
            def f(x,y):
            '''tests two ints for equality
            '''
            return x == y

            Comment

            • Andrew Durdin

              #7
              Re: tweaking @decorator syntax

              On 5 Aug 2004 16:04:00 -0700, Sandy Norton <sandskyfly@hot mail.com> wrote:[color=blue]
              > Here are some more variations.
              >
              > Please copy/paste the code below into your favourite python editor and see
              > how each syntactical variation of the decorator code reads, and how quickly
              > you grok its structure and meaning.[/color]

              *snip examples*

              Of the examples above, I find the "Nested, 'decorate' keyword syntax"
              by far the most clear. It has the following features (in no particular
              order) which I find attractive:

              1. The nesting makes it abundantly clear what the decoration applies
              to, namely the function definitions at the next indentation level. And
              the colon at the end of the "decorate" line is consistent with all
              other Python keywords which result in another indentation level (def,
              if, class, etc.) -- which is one reason why I dislike the "nested
              @decorator" and "nested |decorator|" options. The "Nested, minimal
              decorator syntax" has indentation, but lacks clarity: it appears
              merely to be one or a sequence of function calls followed inexplicably
              by a nested block.

              2. The nesting makes it convenient to apply the same decoration to
              multiple functions, which I guess will be fairly common wherever
              decorators are used.

              3. It doesn't involve adding any additional punctuation to the
              language. I strongly believe that the general lack of punctuation
              contributes greatly towards Python's readability.

              4. The comma-separated list of decorators allows for more compactness
              without sacrificing legibility when multiple decorators are used.


              Whereas I quite dislike the @ syntax, for almost opposite reasons:

              5. In appearance it looks like a special kind of statement; and it is
              not at all obvious to me that it is rather a kind of attribute or
              modifier of the following function definition. I don't know of any
              other construction in Python that performs a similar, unmarked (i.e.
              non-explicit) modification of the following statement. So to me the
              @syntax comes across as extremely un-Pythonic (by that I mean
              radically inconsistent with the conventions of the rest of the
              language). For this same reason, I dislike all the proposed syntaxes
              which involve placing something before the "def" without a subsequent
              indented block.

              6. When using the same sets of decorators for multiple
              functions/methods in the same module/class, the @ syntax is
              inconvenient, as the decorators need to be repeated for each function.
              (Of course, the current (2.3) syntax to achieve the same result is
              similarly inconvenient; the @ syntax adds no benefit in this regard,
              but the "decorate" syntax does).

              7. The @ syntax adds more punctuation to Python's syntax: a Bad Thing.
              Despite the risk of breaking compatibility with some older programs, I
              firmly believe that adding new keywords is a much better idea in
              general than adding new punctuation, because (a) keywords are more
              readable (especially to those unfamiliar with them), and (b) there is
              a very limited supply of punctuation marks on the keyboard, but a very
              large supply of words.

              8. When using multiple decorators, each appears on a separate line.
              This not only confuses things with respect to point 5 above (e.g. does
              the first decorator somehow decorate the second, or do both apply to
              the function?), but also is IMO unnecessarily lengthy, as each line
              has the same basic purpose; In analogy, the latter is similar to the
              difference between
              x = 1
              y = 2
              z = 3
              and
              x, y, z = 1, 2, 3
              where a compact representation is possible and suitable where the
              three variables are relating to the same purpose within the program.

              -- Andrew Durdin

              Comment

              • Stefan Eischet

                #8
                Re: tweaking @decorator syntax - yet another syntax

                Hi,

                I don't know if this particular syntax has been discussed already...
                please feel free to bash me if it was. ;-)

                How about using "is" after the def?

                class spam(object):

                def ni(self) is classmethod: # takes a decorator
                pass

                def foo(self) is (classmethod, synchronized): # or a tuple of
                decorators
                pass

                combination = (classmethod, strange, very_long_descr iption,
                wraps_nicely, blah_blah)

                def bar(self) is spam.combinatio n: # another tuple of decorators
                pass

                def bar2(self) is spam.combinatio n:
                pass

                I think this is quite easy to read and, in comparison to other
                techniques, allows you to first define 'types' of decorated functions
                (like spam.combinatio n or perhaps (Win32API, lives_in_a_dll, )). I have
                no idea if it can be easily implemented, though.

                Regarding the original post below, concerning decorated classes:

                superuseful = (gives_milk, mows_your_lawn, pays_your_rent)

                class foobar(spam) is superuseful:
                pass

                Just my 2 cents.

                Cheers,
                Stefan Eischet

                On 05.08.2004, at 16:17, John Marshall wrote:
                [color=blue]
                > On Thu, 2004-08-05 at 08:41, Sandy Norton wrote:[color=green]
                >> On 4 Aug 2004, Christopher T King wrote:
                >>[color=darkred]
                >>> Of course, I prefer the nested block idea better (either with a new
                >>> keyword or new syntax), but I don't see those (especially the syntax
                >>> one)
                >>> flying anytime soon.[/color]
                >>
                >> I know further discussion of this topic is feeling futile, but one
                >> can only hope.
                >>[color=darkred]
                >>> Unless someone can come up with an idea everyone can agree on Real
                >>> Soon
                >>> Now, I think the whole idea should be dropped and wait until 3.0.
                >>> We'll
                >>> have plenty of time to argue about it then.[/color]
                >>
                >> Agreed.
                >>[color=darkred]
                >>> Sorry about the long rant, but it felt good to get that all off my
                >>> chest.[/color]
                >>
                >> Please, we need more rants like yours. Now if they could somehow
                >> collectively become a 'public outcry' (-;
                >>
                >> I realize my hasty initial post didn't actually show the present 2.4
                >> form,
                >> so I've included it and added your variations for the sake of
                >> comparison:
                >>[/color]
                >
                > With the current choice and the list of alternatives you gave,
                > two things struck me about the location of the decorators
                > in the current choice:
                > 1) They seem to be in the wrong place with respect to
                > what they are affecting.
                > 2) Can decorators easily be extended to apply to class
                > and module?
                >
                > Whether or not the @ or some other operator/keyword/etc. is
                > used, what is more easily understandable/readable?
                > -----
                > class Klass:
                > def __init__(self, name):
                > self.name = name
                >
                > @staticmethod
                > def statmethod1(x):
                > return x
                >
                > @classmethod
                > def classmethod1(cl s):
                > return cls
                >
                > @funcattrs(name ='GvR', language='pytho n')
                > @log(file='func .log')
                > def sayhello(self):
                > print 'hello python world'
                > -----
                > or
                > -----
                > class Klass:
                > def __init__(self, name):
                > self.name = name
                >
                > def statmethod1(x):
                > @staticmethod
                >
                > return x
                >
                > def classmethod1(cl s):
                > @classmethod
                >
                > return cls
                >
                > def sayhello(self):
                > @funcattrs(name ='GvR', language='pytho n')
                > @log(file='func .log')
                >
                > print 'hello python world'
                > -----
                >
                > If the decorators are metadata, that may be extended to affect
                > not only functions or methods, but classes, and modules(?), I would
                > think that wherever a variable or function call would go that
                > would affect the function, method, class, or module, is the
                > right place for a decorator.
                >
                > In the alternative above, it _may_ be that the decorators would
                > only be valid if they are located in specific locations, e.g.,
                > before any non decorator (or comment, or __doc__ information)
                > statements.
                >
                > John
                >
                > --
                > http://mail.python.org/mailman/listinfo/python-list
                >
                >[/color]
                // stefan@eischet. com //

                Comment

                • Hallvard B Furuseth

                  #9
                  Re: tweaking @decorator syntax

                  Andrew Durdin wrote:
                  [color=blue]
                  > it is
                  > not at all obvious to me that it is rather a kind of attribute or
                  > modifier of the following function definition. I don't know of any
                  > other construction in Python that performs a similar, unmarked (i.e.
                  > non-explicit) modification of the following statement.[/color]

                  Right. Today, both the human and the compiler can parse that kind of
                  thing just by looking at the indentation.

                  Still, if we do get a new way to indicate that something is parsed
                  differently, then a special character like @ would be good for that.
                  '@some-directive' in general could be a statement which the compiler
                  reacts to in some way, and decorators could be a special case:
                  @decorator <decorator_name >
                  instead of just
                  @<decorator_nam e>

                  That gives the human reader a keyword he can relate to instead of a
                  special character with an obscure meaning, and the @ character tells
                  him that there is something special about this statement.

                  Though in the case of decorators, I still prefer several of the other
                  suggestions over this one.

                  --
                  Hallvard

                  Comment

                  • Peter Hansen

                    #10
                    Re: tweaking @decorator syntax - yet another syntax

                    Stefan Eischet wrote:
                    [color=blue]
                    > I don't know if this particular syntax has been discussed already...
                    > please feel free to bash me if it was. ;-)[/color]

                    Bash bash.
                    [color=blue]
                    > How about using "is" after the def?[/color]

                    Read the PEP. Basically the same as the "as" variant.

                    Comment

                    • Arthur

                      #11
                      Re: tweaking @decorator syntax

                      On 06 Aug 2004 11:53:29 +0200, Hallvard B Furuseth
                      <h.b.furuseth@u sit.uio.no> wrote:[color=blue]
                      >
                      >Still, if we do get a new way to indicate that something is parsed
                      >differently, then a special character like @ would be good for that.
                      >'@some-directive' in general could be a statement which the compiler
                      >reacts to in some way, and decorators could be a special case:
                      > @decorator <decorator_name >
                      >instead of just
                      > @<decorator_nam e>[/color]


                      It's mildly interesting, and perhaps slightly relevant, that
                      '@some-directive' fools my news reader into thinking there is a email
                      address reference involved.

                      '@' seeming a strange choice for decorator syntax perhaps in part
                      because it already has a much more pandemic meaning, and in that
                      meaning the thing that is in fact '@' the address precedes the
                      symbol. The Python syntax will be the opposite.

                      Though I find the arguments about viusal layout/ indentation the more
                      compelling, and don't think a change of symbol or the introduction of
                      a keyword in substitution for '@' will help with that more substantial
                      issue.

                      That being said, as a founding memeber of CLA (Chicken Littles
                      Anonymous), it is therapeutic to predict publically that Python will
                      survive the @ decorator syntax, should it stick.

                      Art

                      Comment

                      • John Roth

                        #12
                        Re: tweaking @decorator syntax


                        "John Marshall" <John.Marshall@ ec.gc.ca> wrote in message
                        news:mailman.11 95.1091715452.5 135.python-list@python.org ...[color=blue]
                        > On Thu, 2004-08-05 at 08:41, Sandy Norton wrote:[color=green]
                        > > On 4 Aug 2004, Christopher T King wrote:[/color]
                        >
                        > With the current choice and the list of alternatives you gave,
                        > two things struck me about the location of the decorators
                        > in the current choice:[/color]

                        [color=blue]
                        > 2) Can decorators easily be extended to apply to class
                        > and module?[/color]

                        Since I've never gotten my head around metaclasses,
                        I suspect that I'd find the ability to simply declare a
                        function that would "fix" a class at class definition time
                        to be a real help.

                        On the other hand, I'm not entirely sure what
                        you'd use that ability for on the module level.

                        John Roth


                        Comment

                        • Stefan Eischet

                          #13
                          Re: tweaking @decorator syntax - yet another syntax

                          On 06.08.2004, at 14:08, Peter Hansen wrote:
                          [color=blue]
                          > Stefan Eischet wrote:
                          >[color=green]
                          >> I don't know if this particular syntax has been discussed
                          >> already... please feel free to bash me if it was. ;-)[/color]
                          >
                          > Bash bash.[/color]

                          Okay, I was asking for it. ;-) I didn't have the time to read the PEP
                          this morning, but I now have and still like the idea. For my
                          personal taste, it's way better than the ugly @ thing and a bit
                          more explicit than the "[]"-syntax.
                          [color=blue][color=green]
                          >> How about using "is" after the def?[/color]
                          >
                          > Read the PEP. Basically the same as the "as" variant.[/color]

                          Basically, yes. IMO there are a few important differences, though.

                          From the PEP:

                          |Several other syntaxes have been proposed:
                          |def func(arg1, arg2, ...) as dec1, dec2, ...:
                          | pass
                          |
                          |The absence of brackets makes it cumbersome to break long lists of
                          |decorators across multiple lines, and the keyword "as" doesn't have
                          |the same meaning as its use in the import statement. Plenty of
                          |alternatives to "as" [12] have been proposed. :-)

                          This one has optional brackets, so the breaking problems go away. ;-)

                          Just like the "[]" thing, this one should look familiar to Python
                          programmers. Lists, to me, imply that the object can be changed.
                          But tuples are constant, right? Or is it intended to be able to change
                          the decoration at runtime?

                          I personally also dislike the "[]"-syntax because its
                          placement looks quite random to me.

                          "is" is used in another way than usual, though, but I think it's
                          very close to the english meaning of "is".

                          Also from the PEP:

                          |without the intermediate assignment to the variable func. The
                          |decorators are near the function declaration. The @ sign makes
                          |it clear that something new is going on here.

                          "Something new" is exactly what I, personally, wouldn't like to
                          see in Python. How long is it supposed to look "new"? They didn't
                          introduce a new look or funky symbols for new style classes, for
                          example. When people have seen enough of @, will they have to introduce
                          even "newer" symbols? ;-)

                          But regardless of which syntax they choose, I guess I'll get used to
                          it sooner or later.

                          Cheers,
                          Stefan

                          Comment

                          • Jeff Shannon

                            #14
                            Re: tweaking @decorator syntax

                            Andrew Durdin wrote:
                            [color=blue]
                            >
                            >5. In appearance it looks like a special kind of statement; and it is
                            >not at all obvious to me that it is rather a kind of attribute or
                            >modifier of the following function definition. I don't know of any
                            >other construction in Python that performs a similar, unmarked (i.e.
                            >non-explicit) modification of the following statement. So to me the
                            >@syntax comes across as extremely un-Pythonic (by that I mean
                            >radically inconsistent with the conventions of the rest of the
                            >language). For this same reason, I dislike all the proposed syntaxes
                            >which involve placing something before the "def" without a subsequent
                            >indented block.
                            >
                            >[/color]

                            Ah, yes! Thank you for expressing the thing that's been really bugging
                            me about this syntax, but which I hadn't quite managed to put into
                            coherent words. I kept thinking that having all that stuff "stacked up"
                            above the function def looked horribly ugly, but I couldn't quite
                            express why... but I think you've hit on it exactly, there.

                            The fact that it adds punctuation to an otherwise low-punctuation
                            language compounds matters, and I too would rather see a keyword than a
                            punctuation mark (though I do also understand the reluctance to add new
                            keywords). But really, it's the placement rather than the punctuation
                            that truly grates on my eyes.

                            Hm, just as an experiment...

                            def f(x,y):
                            '''tests two ints for equality
                            '''
                            @accepts(int, int)
                            @returns(bool)

                            return x == y


                            I still don't care for the @, but this looks much less jarring to me.
                            At very least, the decorators are much more clearly associated with the
                            particular function.

                            Jeff Shannon
                            Technician/Programmer
                            Credit International

                            Comment

                            • Dave Brueck

                              #15
                              Re: tweaking @decorator syntax

                              Jeff Shannon wrote:
                              [color=blue]
                              > Andrew Durdin wrote:
                              >[color=green]
                              >>
                              >> 5. In appearance it looks like a special kind of statement; and it is
                              >> not at all obvious to me that it is rather a kind of attribute or
                              >> modifier of the following function definition. I don't know of any
                              >> other construction in Python that performs a similar, unmarked (i.e.
                              >> non-explicit) modification of the following statement. So to me the
                              >> @syntax comes across as extremely un-Pythonic (by that I mean
                              >> radically inconsistent with the conventions of the rest of the
                              >> language). For this same reason, I dislike all the proposed syntaxes
                              >> which involve placing something before the "def" without a subsequent
                              >> indented block.
                              >>
                              >>[/color]
                              >
                              > Ah, yes! Thank you for expressing the thing that's been really bugging
                              > me about this syntax, but which I hadn't quite managed to put into
                              > coherent words. I kept thinking that having all that stuff "stacked up"
                              > above the function def looked horribly ugly, but I couldn't quite
                              > express why... but I think you've hit on it exactly, there.
                              >
                              > The fact that it adds punctuation to an otherwise low-punctuation
                              > language compounds matters, and I too would rather see a keyword than a
                              > punctuation mark (though I do also understand the reluctance to add new
                              > keywords). But really, it's the placement rather than the punctuation
                              > that truly grates on my eyes.
                              >
                              > Hm, just as an experiment...
                              >
                              > def f(x,y):
                              > '''tests two ints for equality
                              > '''
                              > @accepts(int, int)
                              > @returns(bool)
                              >
                              > return x == y
                              >
                              >
                              > I still don't care for the @, but this looks much less jarring to me.
                              > At very least, the decorators are much more clearly associated with the
                              > particular function.[/color]

                              Looks much less jarring for me, too. I think Andrew hit the nail on the
                              head.

                              -Dave

                              Comment

                              Working...