[Python-Dev] Re: __metaclass__ and __author__ are already decorators

Paul Morrow pm_mon at yahoo.com
Sat Aug 21 20:25:27 CEST 2004


Phillip J. Eby wrote:
> At 12:29 PM 8/21/04 -0400, Paul Morrow wrote:
> 
>> [I posted this on comp.lang.python.general but I'm not sure how many 
>> of the folks here read that newsgroup, so my apologies if you're 
>> seeing this twice.]
>>
>> Thinking about decorators, and looking at what we are already doing in 
>> our Python code, it seems that __metaclass__, __author__, __version__, 
>> etc. are all examples of decorators.  So we already have a decorator 
>> syntax.
> 
> 
> The items you describe are not decorators, they are attributes.  The 
> current syntax for decorators is 'x = decorator(x)'.
> 

In today's Python that's of course true, but these 'attributes' are used 
to supply meta info about the class. They *describe* the class.  They 
are never intended to be inherited by instances of the class.  So in 
this sense, they are very much more like decorators than (normal) class 
attributes.


> 
>>         def baz(self, a, b):
>>             """ This describes the baz method. """
>>             __synchronized__ = True
>>             __returns__ = None
>>             __author__ = 'Neville Shunt'
>>             # body of baz goes here...
> 
> 
> This syntax already has a different and conflicting meaning in today's 
> Python.  

Yes.  There is a big conflict here.  When I say

     def Foo:
         __author__ = 'me'
         __metaclass__ = M
         var1 = 10
         var2 = 20

although I'm technically defining four class variables, my intention 
behind the first two is very different than my intention behind the 
second two. The first two supply meta information about Foo.  It is 
*not* my intention that those variables be inherited by any instances of 
Foo, because they *don't apply* to instances of Foo --- they apply to 
Foo itself.  They enhance the definition of Foo.  They decorate Foo.

This is true of all magic attributes (as far as I can tell), magic 
methods included.  We define them right alongside instance methods.  But 
we don't intend for the magic methods to be *inherited* by the instances 
so that they become part of the instances interface.  We want to affect 
something much deeper than that (what happens when the instance is 
constructed, which operators may be used on the instance, etc.)

So providing definitions for __xxx__ attributes is not done for the same 
purpose as the other attributes.  They are special.  Therefore, let's 
formally acknowledge that and call them 'decorators'.

> 
> A different such syntax:
>     [synchronized(), returns(None), author("Neville Shunt")]
>     def baz(self, a, b):
>         """ This describes the baz method. """
>         # body of baz goes here...
> 
> has already been rejected on the basis that this too has meaning in 
> today's Python, and that the syntax produces "spooky action at a 
> distance".  That is, it's "magical" that the function calls affect the 
> definition below.
> 

The problem with this example isn't that there's magic involved, it's 
that 1) there's no precedent for idioms like the statement in your 
example to do anything special (to have magical side effects), and 2) 
its not intuitive that the declarations affect the upcoming def.

I don't believe that we have an aversion to magic, where it's clear and 
intuitive what's going to happen.


> Following this logic, expecting assignments to magic names contained 
> within a function's body to magically invoke decorator functions with 
> different names *before and outside the block* where those names are 
> assigned to in the code, seems far less likely to be considered acceptable.
> 

1. The decorator names aren't different than the decorator functions, 
they're the same (minus the leading and trailing double underscores).

2. All magic methods in today's Python are invoked 'magically' (are 
called indirectly; not called directly by any user code).

3. All of the interesting uses of decorators that I've seen proposed 
involve calling functions defined elsewhere (certainly outside of the 
current block of code).



More information about the Python-Dev mailing list