Re: self

Tim Peters (tim@ksr.com)
Thu, 05 May 94 21:01:42 -0400

> [scott, on the differing # of args in method calls & defns]
> ..
> Actually, although I would probably prefer it being implicit on both
> sides, what I should really have said is that I would much rather
> prefer it being symmetric, either explicit or implicit on both sides.

You certainly don't want it explicit on both sides. Then every method
invocation would be the irritatingly redundant and error-prone

object.method(object, arg1, ...)

> The asymmetry bothers me most of all.

I think of it as that the method invocation implicitly passes the first
argument (the object), for my convenience, and the method defn tells the
truth, also for my convenience <wink>.

If "self" were implicit in method defns, that would require a new
reserved word (Guido hates doing that, BTW), and force us to rewrite
existing method defns like the perfectly readable

def __add__(x, y):
return ComplexAdd(x,y)

as the bizarre

def __add__(y):
return ComplexAdd(self,y)

A subtler point is that there's nothing special about a "def" appearing
inside a "class": it's an ordinary function definition, the same as if
it were defined outside the class. All the magic is in the _call_.
E.g., after

class Hmm:
def __init__(self, val):
self.val = val

class Hmm2:
def __init__(self, val): pass

def startup(x, y):
x.val = y

Hmm2.__dict__['__init__'] = startup

class Hmm3:
__init__ = startup

we have

>>> a,b,c = Hmm(1), Hmm2(2), Hmm3(3)
>>> a.val, b.val, c.val
(1, 2, 3)
>>>

I don't recommend the Hmm2 or Hmm3 styles, although on occasion they're
useful. The point is that when you see a "def" in Python, you CAN'T KNOW
whether or not it will end up being used as a method definition. So defs
inside classes can't follow different rules than defs outside classes.

Python allows an extreme amount of dynamic flexibility, and it can be
hard to see all the implications of that. Besides, if symmetry were our
friend, touch typing would be impossible <wink>.

> [destructors]
> ...
> I am a bit confused on the use of the 'del' builtin though.

The short course is that you'll rarely use 'del'. It's probably most
common in anal-retentive modules, that create throw-away named
temporaries as part of their initialization; 'del' is often used in such
cases to purge the temp names from the module's namespace, so that
someone doing 'from Module import *' later won't pick up the useless temp
names.

> Is it necessary to explicitly use it to remove the binding of an object
> to a name

In general, no.

> or will this done implicitly upon scope exit,

"It depends" -- but yes, usually.

> much like C++ ?

Almost exactly _unlike_ C++ <wink>. Scopes have nothing to do with it,
directly. It has instead to do with whether or not there's any way for
you to access the object at any given time. "__del__" gets called when &
only when it's impossible for you to get at the object anymore.

Example:

class Example:
def __init__(self, x):
self.val = x

def __repr__(self):
return 'Example(' + `self.val` + ')'

def __del__(self):
print 'deleting instance', self

def f(n):
a = Example(n)
print a.val * 2
print 'leaving f'

def g(n):
copy = a = Example(n)
print a.val * 2
print 'leaving g'
return copy

print 'calling f'; f(1)
print 'calling g'; thing = g(2)

That prints:

calling f
2
leaving f
deleting instance Example(1)
calling g
4
leaving g

So it's the _object_ that's important, not the scope rules. After f
returned, there was no way to access the object it called "a" internally,
so the object got destroyed. In g, a way to name the object survives the
function invocation, so the object does not get destroyed. C++ doesn't
work this way.

If we add the line

thing = 'hi'

then you'll see

deleting instance Example(2)

as a side effect of the new binding for 'thing': the object to which it
_was_ bound can no longer be named, so it's destroyed.

Please note that you (almost) never have to worry about any of this! The
implementation keeps track of whether or not it's possible for you to name
each object in existence. So long as it is possible for you name an
object, the object will not be destroyed; as soon as you can't name an
object, it is destroyed. In fact, there's no way for you to destroy an
object explicitly; "del" merely breaks a binding, giving you one less way
to access the object.

> BTW, please don't think I'm trying to compare Python to C++. I don't
> particularly care for it actually, but it is useful to convey what I
> mean since so many people are familiar with it.

Well, C++ is great for what it's good at. Alas, what it's good at it is
high-efficiency OO programming, and a great many of its rules in support
of that make a lousy mental model for a dynamically typed and garbage-
collected language like Python. They both pretty much do what they have
to do!

pedantically y'rs - tim

Tim Peters tim@ksr.com
not speaking for Kendall Square Research Corp