[Python-Dev] [Python-checkins] peps: Add PEP 422: Dynamic Class Decorators

Tres Seaver tseaver at palladion.com
Wed Jun 6 02:53:44 CEST 2012


On 06/05/2012 07:38 PM, Nick Coghlan wrote:
> On Wed, Jun 6, 2012 at 9:06 AM, PJ Eby <pje at telecommunity.com> wrote:
>> 
>> 
>> On Tue, Jun 5, 2012 at 5:31 PM, Terry Reedy <tjreedy at udel.edu>
>> wrote:
>>> 
>>> On 6/5/2012 2:26 PM, PJ Eby wrote:
>>>> It's for symmetry and straightforward translation with stacked 
>>>> decorators, i.e. between:
>>>> 
>>>> @deco1 @deco2 [declaration]
>>>> 
>>>> and __decorators__ = [deco1, deco2]
>>>> 
>>>> Doing it the other way now means a different order for people
>>>> to remember; there should be One Obvious Order for decorators,
>>>> and the one we have now is it.
>>> 
>>> 
>>> You and I have different ideas of 'obvious' in this context.
>> 
>> 
>> To be clearer: I've written other APIs which take multiple
>> decorators, or things like decorators that just happen to be a
>> pipeline of functions to be applied, and every time the question of
>> what order to put the API in, I always put them in this order
>> because then in order to remember what the order was, I just have to
>> think of decorators.  This is easier than trying to remember which
>> APIs use decorator order, and which ones use reverse decorator
>> order.
>> 
>> So, even though in itself there is no good reason for one order over
>> the other, consistency wins because less thinking.  At the least, if
>> they're not going to be in decorator order, the member shouldn't be
>> called "__decorators__".  ;-)
> 
> Yeah, I can actually make decent arguments in favour of either order, 
> but it was specifically "same order as lexical decorators" that
> tipped the balance in favour of the approach I wrote up in the PEP.
> 
> It's also more consistent given how the base classes are walked.
> While I'm not proposing to calculate it this way, you can look at the
> scheme the PEP as:
> 
> # Walk the MRO to build a complete decorator list decorators = [] for
> entry in cls.mro(): 
> decorators.extend(cls.__dict__.get("__decorators__", ()) # Apply the
> decorators in "Last In, First Out" order, just like unwinding a chain
> of super() calls for deco in reversed(decorators): cls = deco(cls)


Or, to make it obvious we are treating 'decorators' as a stack::

      while decorators:
          cls = decorators.pop()(cls)


-- 
===================================================================
Tres Seaver          +1 540-429-0999          tseaver at palladion.com
Palladion Software   "Excellence by Design"    http://palladion.com





More information about the Python-Dev mailing list