Explicit Frustration of the Self

Michele Simionato mis6 at pitt.edu
Wed Jan 1 10:05:29 EST 2003


bokr at oz.net (Bengt Richter) wrote in message news:<autar0$91b$0 at 216.39.172.122>...
> On Tue, 31 Dec 2002 14:21:02 -0700, "Bjorn Pettersen" <BPettersen at NAREX.com> wrote:
> >> Someone proposed just a bare leading dot or invisible self name.
> >>=20
> >>   class Foo:
> >>       bar =3D 123=20
> >>       def baz(,arg):
> >>           .arg =3D arg
> >>           return .bar+arg
> >>=20
> >> It's less typing anyway. That's a plus for me.
> >
> >class Foo:
> >    bar =3D 123
> >    def baz(,arg):
> >        class inner:
> >            def baz(,arg):
> >                .arg =3D arg   # <- Foo's arg or inner's arg?
> >        return inner()
> >
The self debate is an old one, but always recurring. One of the first
Python programs I wrote was a preprocessor to implement the "dot
suggestion" (which I saw in the c.l.py thread "A better self") and
which I like very much since it is very readable IMHO. An early
version of my preprocessor is posted in that thread, IIRC. The idea
was to maintain the traditional notation with an explicit self (which
is precious to solve the nested class ambiguity) but to allow a
notational shortcut with an invisible self when there is not risk of
ambiguity, i.e. in 95% of cases.
To type self explicitly when there is no possibility of confusion
bothers me, not only because I have to type unnecessary characters,
but particularly because I am forced to use long identifiers and
therefore long lines of code (I HATE long lines).
Moreover, I think lots of self make code less readable.
I am strongly against the idea of making self a reserved word. The
reasons are two:
i) in nested classes it is convenient to have different selfs, for
instance
"selfbase" and "selfnested";
ii) in metaclass programming and in the case of class methods it is
very convenient to call self "cls".
The possibility of giving a name to self is invaluable in many
specialized
situations; still in most situations self could as well be made
invisible.

There are various disadvantages with the preprocessor idea. A better
solution
is to make use of metaclasses. For instance, one could implement a
name mangling
and add the "self" prefix to all variables starting with "_" (yes, I
know
"_" is reserved for internal variables; you can use another character
if
you wish; unfortunately the dot cannot be used without changing the
Python
grammar).

Here is a simple (but not very much tested) implementation:

--begin selfexpand.py

def selfexpand(cls):
    """Given a class, looks in its methods and expand identifiers
starting
    with _ to self. For instance, _x --> self.x"""
    from re import sub
    from inspect import getsource,isroutine

    def kill_initial_spaces(text):
        lines=text.splitlines(); firstline=lines[0]
        spaces=len(firstline)-len(firstline.lstrip())
        if not spaces: return text
        else: return '\n'.join([line[spaces:] for line in lines])

    def modify(method):
        source=kill_initial_spaces(getsource(method))
        code=sub(r'(?<![\.\w_])_([a-zA-Z_]+)',r'self.\1',source)
        d={}; exec code+'\n' in d
        setattr(cls,method.__name__,d[method.__name__])
 
    for key,val in cls.__dict__.items():
        if not key.startswith('_') and isroutine(val):
            modify(val)

class SelfExpand(object):
    "Classes that inherit from SelfExpand automagically call
selfexpand"
    class __metaclass__(type):
        def __init__(cls,name,bases,dic): selfexpand(cls)
                
class C(SelfExpand):
    x='x'
    y='y'
    def add(self):
        return _x+_y
       

c=C()

print c.add()




More information about the Python-list mailing list