[Tutor] Re: [wxPython-users] Basic question about events and arguments

Magnus Lycka magnus@thinkware.se
Mon Nov 25 17:28:02 2002


Wade Minter wrote:
> > This is probably a pretty basic question, so I apologize for any
> > eye-rolling it may cause - I'm a perl guy trying to use python, and it's
> > tough to get my brain going in a different direction.  :-)

As Yoda said: You have to unlearn what you have learned! ;)
Python is much easier to learn than Perl (at least it was
for me) so you'll get the hang of it soon.

This isn't really a wxPython question, but rather a question
about python's namespaces etc. I'm CCing it to the python tutor
mailing list.

> >     EVT_LISTBOX_DCLICK(self, 60, self.PlayAudio)
> >
> > And the function is defined as:
> >
> >   def PlayAudio(self,event):

Ok, then I assume that it's not a function in the scope of
the module, but a method inside the same class as the EVT_...
I guess you bind the event in __init__. Right? Otherwise the
parameter "self" seems a bit odd.

Have you used object-oriented Perl?

> > However, when I move that function to another .py module (I'm trying to
> > group like functions together in modules), import the module, and call it
> > like:

A Python class must be defined in one file. (As in Perl, right?)
If you want to distribute the definition of a class to several
files, you have to use inheritence. But you don't normally do
that just to spread ot functions in several files. A class should
be a coherent and closely coupled unit that you keep in one file.
Rather if you have common behaviour that is shared between several
classes, you might factor out the common parts and make that a
common base class, but there are other considerations as well. OO
Design is a bit beyond the scope of this mail...

> >     EVT_LISTBOX_DCLICK(self, 60, module.PlayAudio)
> >
> > I get the error
> >
> > TypeError: PlayAudio() takes exactly 2 arguments (1 given)

Tim Hochberg added:
>In the first case, PlayAudio is a method of your class. As a method, self
>gets automagically passed in. In the second case, PlayAudio is function in
>another module and doesn't get self passed in.

Or to put it another way: If you have

class C:
     def playAudio(self, event):
         ...

o = C()

Then

o.playAudio(event)

is just a shorter form of writing

C.playAudio(o, event)

The methods really belong to the class, not to the instance object,
right? There is no corresponding shortcut for functions defined
in modules as there are for methods defined in classes. This is
because no object is an instance of a module the way some objects
are instances of classes (like o of C above).

> >     EVT_LISTBOX_DCLICK(self, 60, mrv_audio.PlayAudio(self,event))
> > NameError: global name 'event' is not defined

Yes, in this case you execute the PlayAudio function (or method?)
when you run the function above, i.e. when you init your class
or module. You want to pass it to the wxPython event handling
mechanism so that it can be called when you double-click on the
listbox. Not at all the same thing.

You have to understand that everything is a first class object in
Python. Like this:

 >>> def x():
...     return "function x returns a string"
...
 >>> def p(f):
...     print "p prints what comes out of the passed in function, namely:", f()
...
 >>> p(x)
p prints what comes out of the passed in function, namely: function x 
returns a string
 >>> p(x())
p prints what comes out of the passed in function, namely:Traceback (most 
recent call last):
   File "<interactive input>", line 1, in ?
   File "<interactive input>", line 2, in p
TypeError: 'str' object is not callable
 >>>

(You don't even have to reference or dereference anything.)

You see? Passing a function object or a function *call* to
another function is not at all the same thing! You can get
around the problem of how to apply parameters by wrapping
the function call inside another function (a lambda is a
kind of small inline function) but in this case I think you've
got the code structured in a strange way, and should look at
that first.

 >>> from __future__ import nested_scope #This feature isn't standard yet.
 >>> def x2(a, b, c):
...     return "%s %s %s" % (a, b, c)
...
 >>> def wrap():
...     return x2('Python', 'is', 'fun')
...
 >>> p(wrap)
p prints what comes out of the passed in function, namely: Python is fun


-- 
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