[Python-Dev] Re: Another approach to decorators.

Jp Calderone exarkun at divmod.com
Thu Aug 12 04:59:06 CEST 2004


David Eppstein wrote:
> In article <un011l2qz.fsf at boost-consulting.com>,
>  David Abrahams <dave at boost-consulting.com> wrote:
> 
> 
>>>class Foo:
>>>
>>>  decorate static:
>>>
>>>    def static1(blah...):
>>>        pass
>>>
>>>    decorate locksFile:
>>>
>>>      def static2andLocks(blah...):  # both decorators appy
>>>          pass
>>
>>Wow, Martin Z's idea (using your keyword) really went "thunk" for me.
>>What decorate does would be very much like what "class" does in some
>>ways.
> 
> 
> class: (and other something: constructs) start a block that can contain 
> any code.  Does this decorate keyword allow e.g. assignments as well as 
> defs and other decorates?  Or loops?  If so what should it mean?  Is it 
> like that locals() gets replaced by a special dictionary-like-object 
> that calls the decorator whenever any of its contents gets set?
> 

   (I have no idea what the original poster intended, however....)

     'decorate' expression ':'
         suite

   could create a nested scope, the locals of which could be passed to 
whatever "expression" evaluates to (or if it is a tuple, do the looping 
thing, since people seem to like that).

   The call can return a dict with which the class dict is updated.

   For that matter, 'decorate' could even be dropped, to avoid 
introducing a new keyword.  I don't think

     expression ':'
         suite

   means anything in the current grammar.  This would mean staticmethod 
and classmethod would no longer work (unless we really want them to - 
they can do type checking on their argument and modify their behavior 
accordingly).  Replacement implementations would be simple.  In fact, 
making any current decorator work with this new mechanism is easy:

     def forall(decorator):
         def new_decorator(namespace):
             for k, v in namespace.items():
                 namespace[k] = decorator(v)
             return namespace
         return new_decorator

     class Foo(object):
         forall(staticmethod):
             def bar(x):
                 print 'spam', x

   Many decorators would probably be used with something like forall, or 
simply support dicts directly.  Of course, many would want to work some 
other way.

   For the PyObjC crowd, I think this would remove a major use of 
metaclasses (as people have argued that metaclasses are hard to 
understand and best avoided for simple decoration, this seems to be a 
good thing).  I can also think of some terrible, terrible metaclass 
hackery in my own code that this would obviate the need for.

   This covers a use case James Knight mentioned as well.  As he pointed 
out, '@' and other proposals only decorate functions (and maybe classes, 
soon).  The example he gave, I believe, was:

     @public
     x = 1

   This doesn't work, but:

     public:
         x = 1

   would.  Now, swallow that scream of horror (I did, barely ;). 
"public" here is intended to be defined as something like:

     def public(namespace):
         __all__.extend(namespace.keys())
         return namespace

   I can see the potential for confusion to new Python programmers here, 
though, if they come from certain other languages.  Perhaps leaving the 
keyword prefix would be best after all.

   Another possibility would be to pass a code object for the suite, 
instead of a namespace.  I am inclined to prefer this, since it more 
closely resembles the other construct which can create a nested scope. 
It adds the burden of exec'ing the code to the decorator, though.  This 
isn't a problem if something like "forall" above is included in the 
stdlib, since the common case is dealt with already (thus people 
desiring class or static methods need not know or care about it), and 
more advanced users will value the power it affords over the minor 
additional effort required to use it.

   Jp


More information about the Python-Dev mailing list