[Python-ideas] Decorators for variables
steve at pearwood.info
Sun Apr 3 00:02:15 EDT 2016
On Fri, Apr 01, 2016 at 08:08:54PM +0200, Matthias welp wrote:
> > So instead of
> > a = Char(length=10, value='empty')
> > you want
> > @Char(length=10)
> > a = 'empty'
> > ?
> If possible, yes. So that there is a standardized way to access changing
> variables, or to put limits on the content of the variable,
But decoratoring a *name binding* isn't going to do that. All it will do
is limit the *initial value*, exactly as the function call does.
a = Char(length=10, value='empty')
the name "a" is bound to the result of Char(...), whatever that happens
to call. But that doesn't change the behaviour of the *name* "a", it
only sets the value it is bound to. Nothing stops anyone from saying:
a = 42
and re-binding the name to another value which is no longer a Char.
Python has no default support for running custom code when binding
arbitrary names to a value. To get this sort of thing to work, you are
limited to attributes, using the descriptor protocol. I'm not going
to explain descriptors now, you can google them, but property is
So let's imagine that Python allows the @ syntax as you request, and go
through the cases to see what that would imply.
For local variables inside functions, or global top-level module
variables, it doesn't give you any interesting power at all. All you
have is an alternative syntax:
x = 999
is exactly the same as
x = spam(eggs(cheese(999)))
right now. You don't even save any characters: 28 (including newlines)
for both. But this doesn't give us anything new and exciting, since x is
now just a regular variable that can be replaced with some other value.
So in this scenario, this sounds boring -- it gives you nothing you
don't already have.
Inside a class, we have the power of descriptors available to us, so we
can use them for computed attributes. (That's how property works, among
many others.) So suppose we have:
x = 999
instance = MyClass()
Now instance.x can be a descriptor, which means that it can enforce
type and value validation rules, or logging, or whatever amazing
functionality you want to add. This is good.
But you can already do this. You just have to write:
x = decorate(999)
instead. If decorate() returns a descriptor, it returns a descriptor
whatever syntax you use.
What benefit do you gain? Well, in the function and class decorator
case, you gain the benefit that the decoration is close to the class or
function header, and you don't have to write the name three times:
method = decorate(method)
But this isn't an advantage in the case of the variable:
x = decorate(value)
You only have to write the name once, and the decoration is not going to
be far away. So just like the global variable case, there's no advantage
to @decorate syntax, regardless of whether you are in a class or not.
More information about the Python-ideas