[Python-ideas] Decorators for variables
Chris Angelico
rosuav at gmail.com
Sun Apr 3 05:57:46 EDT 2016
On Sun, Apr 3, 2016 at 6:02 PM, Matthias welp <boekewurm at gmail.com> wrote:
>> So is there anything left of the assignment-decorator proposal, or is
>> it completely withdrawn?
>
> I think this sums the current open ends up:
>
> - Namespace variables decoration was dismissed by one of Steven's posts, but
> is actually something that might be wanted (via being able to put
> descriptors into namespaces that have a __dict__ accessor (e.g. modules))
> - Variable decoration can be more clear about descriptor/value difference at
> assignment
> - Giving property objects access to their variable's name (e.g. via
> __name__) like functions have would open up quite a bit of possibilities,
> and would mean decorators would get quite a bit more power than what they
> have.
>
> Something that I had said earlier, but what went on a sidepath
> - Decorators may directly *deep* set the behaviour of the variable, and with
> it set the further behaviour of the variable (in the same scope). Such that
>
> @decorator
> var = 20
>
> var = 40
>
> will not reset var to 40, but the var = 40 goes through the descriptor
> (if applied).
>
None of this is possible with decorators *per se*, as they simply
mutate an object as it goes past. The magic you're seeing (and yearing
for) comes from two places: functions have names (so the bit in "def
SOMETHING(...)" actually affects the object constructed, not just the
name it's bound to), and attribute access and the descriptor protocol.
The latter is what makes @property work, but you don't need decorators
to use descriptor protocol - in fact, it's crucial to the way bound
methods are created.
So, let's take your proposals one by one.
> - Namespace variables decoration was dismissed by one of Steven's posts, but
> is actually something that might be wanted (via being able to put
> descriptors into namespaces that have a __dict__ accessor (e.g. modules))
You'll need to elaborate on exactly what this can and can't do.
> - Variable decoration can be more clear about descriptor/value difference at
> assignment
All Python names are in namespaces, so I'm not sure how this is
different from the above.
> - Giving property objects access to their variable's name (e.g. via
> __name__) like functions have would open up quite a bit of possibilities,
> and would mean decorators would get quite a bit more power than what they
> have.
This is fundamentally not possible in the general case; however, you
could easily make a special form of the @property decorator which
*requires* that the attribute name be the same as the function name
that implements it, and then it would work (because function names are
attributes of function objects, while "the name this is bound to" is
not an attribute of anything). It's already accessible, as
ClassName.property_name.fget.__name__; you could make this more
accessible or more discoverable by subclassing property. In fact, you
can even go meta:
>>> class property(property):
... @property
... def name(self): return self.fget.__name__
...
>>> class X:
... @property
... def foo(self): return 42
...
>>> X.foo.name
'foo'
However, this is vulnerable to the same thing that any other "what is
my name" system has: you can rebind anything.
>>> X.bar = X.foo
>>> X.foo = 42
>>> X().foo
42
>>> X().bar
42
>>> X.foo.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'name'
>>> X.bar.name
'foo'
So there's fundamentally no way to say "what name is bound to me"; but
you can quite effectively say "what is my canonical name", depending
on a function to provide that name.
ChrisA
More information about the Python-ideas
mailing list