Are decorators really that different from metaclasses...

Steven Bethard steven.bethard at gmail.com
Tue Aug 31 04:53:59 EDT 2004


Paul Morrow <pm_mon <at> yahoo.com> writes:
> Actually, these look like assignments to local *magic* variables.
> There's the difference.  The double underscores before and after each
> name loudly proclaims that these variables are not like 'normal'
> variables.  They're special in some way.  That's a Python convention.

Note that you're asking for __xxx__ variables to be assignments to the 
function's attributes even though they're in the part of the function that 
gets executed when the function is *called*. Let's look at what examples of 
this behavior might look like for some different objects.

# in the part of a function that is executed when the function gets called
def f():
    __author__ = 'Steve'

# in the part of a class that is executed when the class gets called
class S(object):
    def __new__(cls):
        __author__ = 'Steve'

# in the part of an object that is executed when the object gets called
class T(object):
    def __call__(self):
        __author__ = 'Steve'

Note that the parallel I'm trying to draw here is that in each of these cases, 
the __author__ is assigned to in the part of the definition that gets executed 
when the object is *called*.  Thus f(), S(), and T()() all execute the code 
block containing the __author__ assignment.  Presumably you wouldn't want the 
__author__ statements to assign to the class or the object in the second two 
examples?

Of course, what you really want is for these things to be assigned to in the 
part that gets executed when the object is *defined*.  For a class, this is 
clearly:

class S(object):
    __author__ = 'Steve'

But what gets executed when a function is defined?  Just the def statement, 
the binding of the function name to its body.  To be consistent with classes 
then, your assignment to __author__ should be *in* the def statement.  So what 
you're suggesting, basically, is that the def statement should be extended to 
include any __xxx__ assignments following the docstring. 

Extending the def statement is not unreasonable, but IMHO it should be clear 
that the extensions to the def statement are part of that statement.  There's 
nothing in current Python semantics that would suggest that any assignments in 
a funcdef are part of the def statement. Note that even docstrings, which 
could be reasonably argued to be part of the function definition, cannot be 
included in the def statement by assignment:

>>> def f():
...     __doc__ = "f"
...
>>> print f.__doc__
None

Certainly __xxx__ variables are special in some way.  But are they special in 
the way you want them to be?  AFAICT, *assignment* to __xxx__ variables is 
never what does the magic.  The magic is done when the Python interpreter 
reads the *values* of those variables.  The variables continue to exist in 
whatever namespace they were created in -- AFAICT, current Python __xxx__ 
variable assignments never cause __xxx__ variables to change namespace.

I seems like you want to introduce a substantially new semantics to an already 
existing syntax.  This creates ambiguity...  Ambiguity bad.  Bad, Ambiguitiy, 
bad!  No biscuit! ;)

Steve




More information about the Python-list mailing list