Are decorators really that different from metaclasses...

Paul Morrow pm_mon at
Wed Aug 25 13:20:17 CEST 2004

Steven Bethard wrote:
> Paul Morrow <pm_mon <at>> writes:
>>I believe that (virtually) all __xxx__ attributes have this metadata 
>>aspect (semantics) to them.  When a programmer says
>>    def foo():
>>        __author__ = 'Wilma Flintstone'
>>        __version__ = '0.1'
>>She does not intend for __author__ nor __version__ to be local variables 
>>of foo, used somehow by foo in the calculation of its return value.  To 
>>her they are foo /metadata/ --- attributes of the foo object itself --- 
>>as they contain information that *describes* foo.
> I assume you mean that this is what you'd like a programmer to intend?  If I 
> wrote that, I would intend (and expect) __author__ to be a local variable.  
> I'm not saying that I couldn't be retrained.  I'm just saying that right now, 
> I would not expect it to be otherwise.

What I mean is that this is what (I believe) veteran Python programmers 
always intend, because it's a Python convention (although I've never 
actually seen it described quite like this --- as metadata).

Here's what PEP 8 ( has to say 
about __xxx__ attributes:

       __double_leading_and_trailing_underscore__: "magic" objects or
       attributes that live in user-controlled namespaces,
       e.g. __init__, __import__ or __file__.  Sometimes these are
       defined by the user to trigger certain magic behavior
       (e.g. operator overloading); sometimes these are inserted by the
       infrastructure for its own use or for debugging purposes.  Since
       the infrastructure (loosely defined as the Python interpreter
       and the standard library) may decide to grow its list of magic
       attributes in future versions, user code should generally
       refrain from using this convention for its own use.  User code
       that aspires to become part of the infrastructure could combine
       this with a short prefix inside the underscores,
       e.g. __bobo_magic_attr__.

Here's a link that gives some examples of them:

Sure veterans know that if it looks like a local variable definition, 
then it is one.  But my point is that (IMO) they don't normally rely on 
that aspect of __xxx__ variables.  You'll almost never see a function 
that examines its own metadata in the computation of its result.

>>Likewise, when she defines __lt__, __getitem__, __init__, etc. as part 
>>of a class, they will not typically be called by methods of the class or 
>>users/consumers/clients of the class [*] the way that 'normal' 
>>attributes will.  They contain meta info that describes a deeper level 
>>of class behavior.
> This seems a little misleading to me.  The only reason these methods are 
> special is because they override operators (something like "<", "[]", and "()" 
> respectively).  You could provide a class with /exactly/ the same 
> functionality without ever implementing any of these methods.  (Well, minus 
> __init__, but that was a special case in your discussion too.)  The only thing 
> that implementing these methods does is allows your user to access these 
> methods through an operator shorthand.  A simple example:
> class Identity:
>     def get(self, x):
>         return x
>     __getitem__ = get
> How is __getitem__ any more "metadata" then get is?  They provide exactly the 
> same functionality.  The __getitem__ declaration just allows you to access the 
> get method using "[...]".

Well, but that's a big difference.  __getitem__ has a much deeper 
meaning than your 'get'.  Defining it actually changes which syntax 
you're allowed to use on instances of your class.  Now you can do things 

    ident = Identity()
    print "%(alpha)s, %(beta)s, %(gamma)s" % ident

> Are you trying to say that "metadata" is the same thing as "operator shortcut"?

Not exactly, but it would include defining those.  One way to think 
about metadata is that it includes all information *about* an object, 
but no information *used by* the object.

If we were to have a conversation about this conversation, then we would 
be having a "meta-conversation."  /metadata/ is data that describes 
data.  metadata for a function would be data that describes the 
function; data *about* the function as opposed to data *used by* the 
function.  For example:

    def circumference(diameter):
       """ This is a docstring.  It's metadata for this function. """
       __author__ = 'Paul Morrow'      # more metadata
       pi = 3.14                       # not metadata
       return pi * diameter


More information about the Python-list mailing list