Getting rid of "self."

BJörn Lindqvist bjourne at gmail.com
Sun Jan 9 19:51:07 EST 2005


Thank you for your replies. It is very nice to see that a thread you
started is generating so much discussion, but please, I have read the
previous debates so I know all about what people think about self.
Spare the "you shouldn't do that" and "self is here to stay" replies
to the threads in which people are actually suggesting changing the
syntax. :)

I know the solution I presented is not working ideally, because you
have to use self to assign to instance attributes like "self.hi =
'baby'".

> Sean Ross:
> http://starship.python.net/crew/mwh/hacks/selfless.py

That's excellent! There is one small problem with the code though:

.class Hi(Selfless):
.    __attrs__ = ["x"]
.    def __init__(x):
.        self.x = x

In this case, I think the Python interpreter should realise that the
parameter x shadows the attribute x. But the selfless code has
problems with that. I want it to work exactly like how the situation
is handled in Java and C++.

> Alex Martelli:
>> Björn Lindqvist:
>> I think it would be cool if you could refer to instance variables
>> without prefixing with "self." I know noone else thinks like me so
> Some do -- Kent Beck's excellent book on TDD-by-example has a specific
> grouse against that in the chapter where he develops the unittest module

I have to get myself that book. 

> Alex Martelli:
> A decorator can entirely rewrite the bytecode (and more) of the method
> it's munging, so it can do essentially anything that is doable on the
> basis of information available at the time the decorator executes.

Which I believe means that the instance variables have to be declared
in the class? I am content with declaring them like the selfless
approach does:

__attrs__ = ["hi", "foo"]

It's not optimal because it would lead to some "name duplication" when
a class is __init__:ed.

.__attrs__ = ["hi", "foo"]
.def __init__(_hi, _foo):
.    hi = _hi
.    foo = _foo

I guess you can solve that adequately by using one of the recipes from
the Cookbook that automagically initialises an objects variable
depending on which variables was passed in the parameter list. Another
alternative would be not to declare the variables in an __attr__ list,
and instead let them be "declared" by having them initialised in the
__init__. I.e:

.def __init__(hi, foo):
.    self.hi = hi
.    self.foo = foo

When the metaclass then does it magic, it would go through the code of
the __init__ method, see the assignments to "self.hi" and "self.foo",
decide that "hi" and "foo" are attributes of the object and replace
"hi" and "foo" in all other methods with "self.hi" and "self.foo". The
downside is that it probably could never be foolproof against code
like this:

.def __init__(hi, foo):
.    if hi:
.        self.hi = hi
.    else:
.        self.foo = foo

But AFAIK, that example is a corner case and you shouldn't write such
code anyway. :)

> Alex Martelli:
> You do, however, need to nail down the specs.  What your 'magic' does
> is roughly the equivalent of a "from ... import *" (except it
> ...
> Then, you must decide whether this applies to all names the method
> accesses (which aren't already local).  For example, if the method
> has a statement such as: 
>   x = len(y)

All names should be checked like this:
1. Is the name in the parameter list? If so, do not rebind it.
2. Is the name in the objects attribute list? If so, prepend "self."
3. Do stuff like normal.

Example:

.class Foo(Selfless):
.    def __init__(x):
.        print x
.        self.x = x*2
.    def meth():
.        x = x + 10
.        print x
.    def meth2(x):
.        print x
.        print self.x
.        self.x = x
.
.o = Foo(50)
.print o.x
.o.meth()
.o.meth2(12)
.print o.x

Outputs:
50
100
110
12
110
12

> Alex Martelli:
> If you can give totally complete specifications, I can tell you
> whether your specs are doable (by a decorator, or other means), how,
> and at what cost.  Without knowing your specs, I can't tell; I can
> _guess_ that the answer is "probably doable" (as long as you're not
> demanding the code in the decorator to be an oracle for the future,

This is promising, I'm content with whatever slowdowns necessary as
long as I can prove those who say "you can't do it" wrong. :) It seems
to me that it should be doable by having the metaclass that modifies
the class go through the class and bytecode-rewrite all its methods.
So there has to be a big slowdown when the class is created, but after
that, it should execute at pure Python speed? That doesn't seem to
hard, and pretty robust too since bytecode doesn't change so often.
And THEN I'll rewrite python-mode so that it syntax highlights member
attributes! It will be cool.

-- 
mvh Björn



More information about the Python-list mailing list