[Tutor] Tutor Digest, Vol 32, Issue 72

Luke Paireepinart rabidpoobear at gmail.com
Wed Oct 18 06:14:32 CEST 2006


> I tried it and it did work this time, thanks so much.  Your effort may keep 
> me trying bit by bit to gain a little profiency.
>   
I'm glad that you're not going to give up just yet!  Don't worry, I have 
much more effort in store for you :)
> And yes, I believe I see how much of this ought to work now.  I am just 
> going to keep going over how one assigns a variable like savefile to a built 
> in function like open() but then attaches a method to it such as when you 
> write savefile.write.  I think if I work with that enough I will come to see 
> it as intuitive; for now it still is unintuitive.   Thanks again.
>   
Okay, I think I can explain this :)

Starting from the beginning:
a variable is a name that refers to an object.
it's nothing more than this.
It can refer to any type of object, a class, a class instance, a class 
method, a function, a class attribute,
a list, a tuple, whatever.  It's just a way that the programmer can tie 
a name to an object so it can be used later.

A function is a collection of expressions.
There are different types of functions.
This is what they do:
Takes zero to many inputs, and returns (outputs) one object.
Takes zero to many inputs, and modifies something outside of the function.
Takes zero to many inputs, and modifies something outside of the 
function, and returns (outputs) one object.

The first kind is the most conventional function.
The second kind is called a null or void function, because it doesn't 
return anything.
The point of these functions are their side-effects.
The third kind is something that you should avoid, which is a function 
that has side-effects as well as a return.

Here are examples of these:

#first type
def add_five(aNumber):
    return aNumber + 5

#second type
def append_five(aList):
    aList.append(5)

#third type
def append_and_add_five(aList):
    aList.append(5)
    return aList[0] + 5

#---------------

And testing them:
 >>> add_five(5)
10
 >>> a_list = [1,2,3,4]
 >>> append_five(a_list)
 >>> print a_list
[1,2,3,4,5]
 >>> a_list = [1,2,3,4]
 >>> append_and_add_five(a_list)
6
 >>> print a_list
[1,2,3,4,5]


#-------------

Some things to note:
You have a list a_list in the global scope that has the value [1,2,3,4].
when you pass it to the append_five function as 'aList',
and then print it out, a_list is [1,2,3,4,5].
This is because python doesn't pass _copies_ of variables to functions,
it passes what that variable is referring to, UNLESS the variable is 
immutable (you can't change it.)
For immutable variables, a new object will be created to contain the value.
This only makes a difference with lists, because lists are mutable.
A good way to rationalize this:

#since integers are immutable, these actually refer to two separate 
copies of an int object containing a 5.
 >>> a = b = 5
 >>> a += 5
 >>> a
10
 >>> b
5

#since lists are mutable, these refer to the same object.
 >>> a = b = ['hello,']
 >>> a.append('world!')
 >>> a
['hello,','world!']
 >>> b
['hello,','world!']

So think of it like this:

aVariable = 1
def aFunction(anotherVariable):
    print anotherVariable
    #... other useful stuff....

When you make the call aFunction(aVariable)
what's happening is this:

anotherVariable = aVariable
print anotherVariable
# ---- other useful stuff -----

It's slightly more complicated than this, (namespaces and such), but 
that's the main idea.

so this example:

aList = [1,2,3,4]
def aFunction(anotherList):
    print anotherList
    #... other useful stuff ....

when you make the call aFunction(aList)
it's doing
anotherList = aList
print anotherList
# --- other useful stuff ----

and as we saw above, if you do a = b, and b = a list, then a is the SAME 
list, not a COPY of that list.
Hope that makes sense.

Also, note that 'print' is in itself a side-effect, because it's 
modifying things that are outside the function,
so if you have a function printing things, you shouldn't have that 
function return anything.
Or so I've been told after a year of Computer Science courses :)


The reason I explained this is to hopefully make the next section I'll 
explain more clear.

>going to keep going over how one assigns a variable like savefile to a built 
>in function like open() but then attaches a method to it such as when you 
>write savefile.write.  I think if I work with that enough I will come to see 
>it as intuitive; for now it still is unintuitive.   Thanks again.

Okay, you're thinking of this in the wrong way.

#given this definition,
def aFunction(a):
    print a

 >>> myFunction = aFunction
 >>> myFunction
<function aFunction at 0x009E7A70>
 >>> aFunction
<function aFunction at 0x009E7A70>

That is what assigning a variable to a function looks like.
What I was doing was something completely different.

 >>> myFunction = aFunction('hello') #notice the parenthesis!
hello

Do you see what the difference is?
Because functions are objects, you can assign variables to them if you want!
You can do a = b= c= d= e= aFunction
and call all of these the same way.
However, they are just references to the function (remember, we talked 
about references earlier?)

Generally, we don't care about the function itself, but what it 
_returns_ or what its side-effects are.

So when I type
myFunction = aFunction('hello')

a temporary variable (we'll call it temp for easy explanation, but it's 
called something different)
is created, containing the string 'hello.'

temp = 'hello'
then the aFunction is called, which results in
a = temp
print a

(this isn't really what's happening, but it's close)

so when I say something like this:

 >>> f = open('filename.txt')

what's happening is that the function 'open'
is doing all its stuff and creating an object that contains the 
information for the file,
and returns it.
Remember, whenever there are parenthesis, it's a function call, we're 
not assigning a variable to refer to a function itself.

You can see this pretty clearly by outputting f.

 >>> f
<open file 'filename.txt', mode 'r' at 0x009D3650>

If we were assigning f to be the actual function 'open', you'd see 
something similar to what we saw before.
 >>> f = open
 >>> f
<type 'file'>

The reason it doesn't say "function 'open' at 0x009....." is because 
it's a built-in, but the premise is the same.

So I'll take you through my code again, this time explaining what's 
happening now that I know what you're struggling with.


>    def OnSaveButton(self, event):
Just ignore this, we don't care about any of this stuff.

>        savefile = open('test.txt','w')

What this is doing is (to explain in human terms)
talking to the function named 'open' and saying "please go get all the information for this file
for me, and give me a bunch of methods that deal with it, because I don't want to have to deal
with the nitty-gritty of reading and writing files at the operating-system level."
'open' gladly obliges, and constructs some object.
if we were to do 'print savefile' right now, we'd get
<open file 'test.txt', mode 'w' at 0x00.......>
this is an object that has many methods that 'open' has been nice enough to create for us
that help us deal with files.
we can figure out which methods it has by doing a directory listing, much like you'd do on an OS.
>>> dir(savefile)
and we get:

['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'close', 'closed', 'encoding', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']

as you can see, one of these methods that the class instance (object) has is the write method.
So now that we know it's available to us,

>        savefile.write(self.textCtrl1.GetValue())

This line is a little complex. Let's break it up to make it easier to read.

textBox = self.textCtrl1

even though self.textCtrl1 is a method of the current class instance 
(which is what self means)
we can still assign a variable to it.

text = textBox.GetValue()

this will give us everything that's in the textBox (which is 
self.textCtrl1 also) and make a
string object that contains the text. then it'll point the variable 
named 'text' to this object
so we don't lose it and so we can use the data later.

savefile.write(text)

this will output the text that we just got into the file.

 > savefile.close()
Another one of those methods that the file object has, if you go look, 
is 'close'.
When you close a file, it flushes the buffer and such, and unlocks it 
can be deleted and stuff.
You should always close your files, just in case, even if it's at the 
end of a program.



Well, that was a bit of a long-winded response, and I hope I didn't 
confuse you further, but of course
anywhere that I was just completely incoherent, just point it out and 
I'll try to explain it more proficiently.
:D

Also, have you tried working through Alan Gauld's tutorial?
I'm sure he explains these concepts much better than I do ;)

Good luck with the Python!
-Luke


More information about the Tutor mailing list