Fwd: Re: [Tutor] instance variables and the instance dictionary

Magnus Lycka magnus@thinkware.se
Fri Jan 10 19:31:26 2003


I suppose this was meant for the list:

>Date: Fri, 10 Jan 2003 16:26:46 -0700
>From: Poor Yorick <gp@pooryorick.com>
>Subject: Re: [Tutor] instance variables and the instance dictionary
>
>Magnus Lycka wrote:
>>This is not different than:
>>
>> >>> self = "Nosir. Not a scrap. I was deliberately wasting your time, sir."
>> >>> def x(self):
>>...     self = "Well I'm sorry, but I'm going to have to shoot you."
>>...
>> >>> print self
>>Nosir. Not a scrap. I was deliberately wasting your time, sir.
>> >>> x(self)
>> >>> print self
>>Nosir. Not a scrap. I was deliberately wasting your time, sir.
>Or, to illustrate it using Bob's code:
>
> >>> class xx(list):
>    def clear(self):
>        self = []
>        print 'this is self', self
>
> >>> a = xx(['1','2','3'])
> >>> a
>['1', '2', '3']
> >>> a.clear()
>this is self []
> >>> a
>['1', '2', '3']
> >>>
>
>So I suppose that the magic is in the ".", which is what tells the 
>interpreter to create the identifier in a different namespace.  So on a 
>lower level objects disappear and all you have are namespaces, 
>identifiers, values, functions, and virtual method tables.  And out of 
>those things emerges object oriented programming.  Is that close?

Well... I don't know. The only problem with Bob's code is that he forgot
that "self" is just a local variable in the method, and that assignment
means that the local variable will "forget" it's previous value, and refer
to a new object.


There are objects everywhere. Functions, modules, integers, strings, lists.
They are all objects. If you meant just instance objects, they don't
disappear. They are as real inside the methods defined in the class as
anywhere else. They are passed in--as you know--to all method calls in the
first parameter, the one we by convention call self. But inside the method,
there is no special magic for the bound instance object. Initially, self
will refer to it, and we can access it and change it as we like, but if we
do "self = <something else>" in the method, we have lost our reference to
the instance object. Clear as the dark sky outside my window...

I'd say, that there is no magic here. Everything is consistent.

Let's try to analyze one of the most fundamental things in Python. The
assignment statement.

x = 5

What do we have here? First of all, on the Right Hand Side (RHS)
we have an integer object. Python will find a place for that in
memory, and store it there. Secondly, on the Left Hand Side (LHS)
we have a variable name, x. From now on, until further notice (or
end of scope) x will refer to the integer object 5. If x existed
before this assignment, it no longer points to whatever object it
pointed to before. The reference count for the object it pointed
to before is decremented, and it will be garbage collected if x
was the only reference to it.

Let's say we continue with

y = x

Now the LHS is another variable, but that doesn't change any principle. The
big difference is that the RHS is not an object, but a variable. So, while
"x = 5" means "x should point to the integer 5 from now on", "y = x" means
"y should from now on point to whatever object x is currently pointing to".
For those familiar with C++, we can say that all python variables behave as
references.

But the LHS isn't always a variable either. For instance if we write

l = [1]

we have a statement of the same type as "x = 5", but we can make this
more interesting by writing:

l[0] = x

In this case, the LHS is not a variable, but location 0 in the list
object that l points to. The result will be that l will no longer
be a list with a single 1 in it. It will be a list with a single 5
instead. l[:] = x would mean the same thing in this case, but it
would have had a different consequence if l had contained more that
one value.

Lists are mutable objects, and one way of mutating lists is through
assignments to slices of lists. Other ways of mutating lists, such
as .append() are not assignments.

As you note, we can also give a more "complete address" of a variable
in a different scope. If m is a module "m.x = 5" means "The global
variable x in module m should from now on point at the integer
object 5". If m is a class or a function or an instance object, it
would mean that "The attribute x of m should from now on point at
the object 5". But there is no magic in this I think. (Can other
objects than classes, instances and functions have attributes?)

Your code above is not really different than writing.

 >>> class xx(list):
    pass

 >>> a = xx(['1','2','3'])
 >>> a
['1', '2', '3']
 >>> b = a
 >>> b = []
 >>> a
['1', '2', '3']
 >>>

Or to make it simpler.

 >>> a = ['1','2','3']
 >>> a
['1', '2', '3']
 >>> b = a
 >>> b = []
 >>> a
['1', '2', '3']
 >>>

The object that a variable (local or global or an attribute of
some other object) pointed to before an assignment statement is
not influenced be the assignment.

To make it very brief:

If we write...

b = a
b = ()

...nothing will change in the object that variable a points to,
and nothing will happen to the variable a.


-- 
Magnus Lycka, Thinkware AB
Alvans vag 99, SE-907 50 UMEA, SWEDEN
phone: int+46 70 582 80 65, fax: int+46 70 612 80 65
http://www.thinkware.se/  mailto:magnus@thinkware.se