Are decorators really that different from metaclasses...
Paul Morrow
pm_mon at yahoo.com
Tue Aug 31 08:20:53 EDT 2004
Steven Bethard wrote:
> 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?
>
In all of your examples, the __author__ assignments apply to the object
being defined. In the first example, that's the function f. In the
second example that's the method __new__, and the method __call__ in the
3rd example.
Note that this is true, /even in today's Python/. Your intention behind
each __author__ definition in your examples is *not* to create a local
variable. Your function/method (most likely) is not going to use
__author__ when it executes. Instead you are adding to the definition
of the function/method.
What I'm wondering is whether we can stop thinking of assignments to
magic attributes that immediately follow the docstring (if present) as
something that gets executed when the function is called. I think that
we can. I think that --- because of the names of these variables
(author, version, features) --- they will obviously and intuitively be
associated with the function's definition, not it's execution. That's a
point a lot of us have been forgetting here. These variables don't
sound like something the function would use in it's calculation. So
that, plus the fact that they are specially decorated (leading and
trailing underscores), plus the fact that they immediately follow the
docstring categorize them as part of the function's definition, not
execution.
But why speculate. Let's see if this is really going to be unclear in
practice. Ask someone who has never seen Python before which are the
local variables in the following def.
def circumference(diameter):
"""Calculate the diameter of a circle."""
__author__ = 'Paul Morrow'
__version__ = '0.1'
pi = 3.14
return pi * diameter
> 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.
And the binding of the __doc__ variable, if a docstring is present.
> 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.
>
Yes.
> 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?
Not yet, /formally/. But /in practice/ this is how they are used (to
make meta statements about the thing being defined).
There's no need for a new syntax here. We don't need more words in our
language, or anything that makes our code less readable [*].
[*] Have you seen the decorator proposals?
> 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.
>
The assignments to __xxx__ variables (immediately following the
docstring, if present) would occur in the namespace of the object
(function/method) being defined. The assignments would not cause them
to change namespaces.
> 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! ;)
>
I maintain that the author's intention behind these assignments is what
we should focus on. When we define a __xxx__ variable inside of a
function def, we are (most likely) making a meta statement about the
function. We are not defining a local variable to be used later in the
execution of the function. So this proposal would not be changing the
meaning of the __xxx__ assignments in practice. It would merely be
formalizing them.
Paul
More information about the Python-list
mailing list