Are decorators really that different from metaclasses...

Jess Austin jess.austin at gmail.com
Fri Aug 27 20:35:33 EDT 2004


Paul Morrow <pm_mon at yahoo.com> wrote in message news:<mailman.2478.1093564289.5135.python-list at python.org>...
> Nope, that was me alright.  I don't want a function to have access to 
> it's metadata.  Nothing's changed about that.  I want to be able to 
> specify a function's metadata inside the function def, where it seems to 
> most appropriately belong.

So you have:

def foo(x):
    __meta_variable__ = 42
    variable = 5
    return dir()

And you're volunteering to explain to a newbie, or even a nearly
intermediate programmer like myself, why the list that is returned
from this function contains 'x' and 'variable' but not
'__meta_variable__'?  I'm sorry, but this is unreadable and is a
dramatic break from Python convention.

A variable binding inside a block is available in that block and in
contained blocks (method blocks aren't properly understood as being
contained within the class block), after the statement setting the
variable has executed.  A variable defined inside a block is not
available outside it without indexing through another binding created
by an import or class statement.  This makes Python code easy to read.
 You propose to turn this on its head for a particular class of
variables defined within function blocks.  No amount of reasoning or
argumentation will justify such a maneuver.

> Others seem to want to specify a function's metadata outside of the 
> function def, which just doesn't seem pythonic (IMO).

If you really understood Python's scoping rules, you would know that
this opinion is the opposite of the truth.  Of all the current
incarnations of function "metadata", only one may be set within the
function, and that one is not set using a standard binding statement:

>>> def bar():
...     """docstrings are the exception not the rule"""
...     __meta_doc__ = """Please don't assume otherwise"""
...
>>> dir(bar)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__',
'__get__', '__getattribute__', '__hash__', '__init__', '__module__',
'__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__str__', 'func_closure', 'func_code',
'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

In the returned list, only '__doc__' was affected by characters in the
function suite, and those characters did not comprise a binding
statement within the function block.  So in this respect '__doc__' is
not an exception to the rules about name binding in function blocks
either.

I think you're getting confused via a false analogy between function
blocks and class blocks.  It's true that bindings set within a class
block are accessible through class or instance objects.  This stateful
binding access is what is fundamental about classes, while
operator-associated method names are sugar, or "magic" if you prefer. 
Function block binding statements are instructions for function
_execution_, class block binding statements are instructions for class
_creation_, and there's the difference.  Any meta-meaning that the
actual name used in a binding statement might have is purely
incidental, in that the function or class is created in the same
fashion whether a given name has a magic meaning or not.  Certain
multiple-underscore names do change the behavior of a class, but only
one relatively hackish name (__metaclass__) changes how it is created.
 Class statements have to deal with creation because they have state,
thus they must have an initial state.  Functions do not have state,
although the objects we use to access them (function or generator
objects) from the _outside_ do.  It seems hard to support pushing
bindings with persistent state into the function block when it has
never had this before.

I appreciate your persistence in error; it has provided me with the
opportunity to gain knowledge in an area about which I previously had
only intuition.  b-)  In broader commentary, as I've said, pep318
isn't really about metadata.  One reason is that metadata isn't that
important.  Data only needed by an outside system should be kept
there.  If any layer of code uses particular data, that layer should
be responsible for maintaining such.  Python already accomodates this
more correct style of information management, and pep318 might
increase this accomodation.

yours,
Jess



More information about the Python-list mailing list