faqts : Computers : Programming : Languages : Python : Snippets : Deep Magic

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

18 of 18 people (100%) answered Yes
Recently 10 of 10 people (100%) answered Yes

Entry

I don't like typing "self." all the time, can I avoid it?
I don't like having to type "self." all the time, can I avoid it?

Jul 23rd, 2002 06:25
Michael Chermside, Duncan Booth, Greg Ewing


I don't like having to type "self." all the time in methods like this:
    def doFormula(self):
        return math.cos(self.t) * self.x ** self.y + self.z
Is there a way around it? Shouldn't I be able to just do this:
    def doFormula():
        return math.cos(t) * x**y + z
After all, it works in [Java / C++ / favorite language].
Answer #1:
No. There is no way around it. This is done intentionally. Try out the
Python way... explicit is better than implicit. In Python, unlike
[favorite language] you can always tell when you're dealing with a
global, a local, or an instance variable (and without searching through
15 different source files!), and this is a Good Thing[tm].
Answer #2:
If you are really just worried about the amount of space that it takes
up, then go ahead and use "s" instead of "self" (some people use "_"
instead). It's not traditional, but it works just fine, and requires
fewer chraracters (but we recommend answer #1 instead!).
    def doFormula(s):
        return math.cos(s.t) * s.x**s.y + s.z
Answer #3:
No, you REALLY can't put up with this. You have a mathematical formula
to write, and all those "self."'s are just totally unacceptable... they
make the math difficult to read.
How about writing the formula as a separate function? It would look
something like this (note the extra dict argument we ignore which makes
this trick work):
    # Outside of class
    def formula(x, y, z, t, **_):
        return math.cos(t) * x**y + z
    # Inside the class
    def doFormula(self):
        return formula(**self.__dict__)
What we do here is to pass the class dictionary (which contains self.x,
self.y, etc) as keyword arguments to the separate function formula(),
which looks for x, y, z, and t, and then ignores (but accepts) all other
arguments. The only problem with this situation is that invoking a
function (particularly invoking one with keyword arguments) adds a bit
of overhead in Python.
Answer #4:
No, you REALLY can't put up with this. You REALLY must have your
auto-access to instance variables, and you WON'T put up with calling an
extra function. Well, we warned you. But here is a module by Duncan
Booth which will do what you want. But PLEASE use with care. (Works in
Python 2.2, perhaps other versions.)
----- begin magic.py -----
# How to make methods magically access member variables.
#
import new
from math import sin, sqrt
def withself(method):
    '''withself(method)
    Converts an unbound method into a method where all global variables
    are assumed to come from the instance.
    Global variables are accessible only if the instance sets
       self.__builtins__=globals()
    Builtins are not accessible unless you do:
       self.__builtins__=__builtins__
    '''
    def callwith(self, *args, **kw):
        f = new.function(method.func_code,
            self.__dict__,
            method.func_name,
            method.func_defaults or ())
        return f(self, *args, **kw)
    return callwith
class C:
    def __init__(self, x, y, z):
        self.x, self.y, self.z = x, y, z
        # Makes global variables visible to formulae
        self.__builtins__ = globals()
    def formula(self):
        return x + y - z
    formula = withself(formula)
    def updater(self):
        global x
        x += 1
    updater = withself(updater)
    def formula2(self):
        return sqrt(y*z)
    formula2 = withself(formula2)
test = C(3, 7, 2)
print test.formula()
test.updater()
print test.formula()
print test.formula2()
----- end magic.py -----