List Info

Thread: class methods as argument




class methods as argument
user name
2007-02-10 05:39:30
Hi,

I want to do something like this, don't know how to properly
explain it,
so I just give you some example code

>>>class Foo(object):
>>>	def method(self, arg):
>>>		print arg

>>>def doSomething(object, func):
>>>	object.func("test")

>>>object = Foo()
>>>doSomething(object, Foo.method)

I want to execute the class method given as argument,
but this obvious doesn't work, but I don't know how to
get it work,
Is it possible?
and how?

Thanks

_______________________________________________
Tutor maillist  -  Tutorpython.org
http://
mail.python.org/mailman/listinfo/tutor

Re: class methods as argument
user name
2007-02-10 08:44:44
On Sat, 10 Feb 2007 22:10:52 +1000
Jonathan McManus <jonathanacss.net.au> wrote:

> It's pretty easy to make this work, actually. The issue
is in the
> "doSomething" method.
> 
> > >>>class Foo(object):
> > >>>	def method(self, arg):
> > >>>		print arg
> > 
> > >>>def doSomething(object, func):
> > >>>	object.func("test")
> 
> Here, it's looking for a method of the "Foo"
object (object) called
> "func" (AttributeError: 'Foo' object has no
attribute 'func'), instead
> of replacing "func" with
"Foo.method". 
> 
> What you need to do is:
> 
> >>> def doSomething (object, func):
> >>>	func(object, "test")
> 
> This means that you are calling the method (explicity
passed as being
> a method of Foo), as well as supplying the actual
object as the first
> argument (the required self for classes).
> 
> >>> object = Foo()
> >>> doSomething(object, Foo.method)
> test
> 
> Hope that helps.
> 


Thanks,
that I've didn't come up with that myself!
It's indeed easy!
_______________________________________________
Tutor maillist  -  Tutorpython.org
http://
mail.python.org/mailman/listinfo/tutor

Re: class methods as argument
country flaguser name
United States
2007-02-10 06:55:54
thomas coopman wrote:
> Hi,
> 
> I want to do something like this, don't know how to
properly explain it,
> so I just give you some example code
> 
>>>> class Foo(object):
>>>> 	def method(self, arg):
>>>> 		print arg
> 
>>>> def doSomething(object, func):
>>>> 	object.func("test")
> 
>>>> object = Foo()
>>>> doSomething(object, Foo.method)
> 
> I want to execute the class method given as argument,
> but this obvious doesn't work, but I don't know how to
> get it work,

First a quick note - don't use object as a parameter or
variable name, 
it will hide the definition of the built-in object class.

You are very close. Foo.method is called an 'unbound method'
of class 
Foo. The syntax for calling an unbound method is to pass a
class 
instance as the first argument, followed by the actual
argument list. It 
is actually the same argument list that you use when you
declare the 
function (starting with self).

So your example can be written this way:

In [4]: class Foo(object):
    ...:     def method(self, arg):
    ...:         print arg

In [6]: o=Foo()

In [8]: def doSomething(obj, func):
    ...:     func(obj, "test")

In [9]: doSomething(o, Foo.method)
test


A more common way to do this is to use a 'bound method'.
That is what 
you get when you refer to instance.method instead of
Class.method. A 
bound method includes a reference to the particular instance
and can be 
called like an ordinary function. Rather than passing the
instance and 
the unbound method to doSomething(), just pass the bound
method as a 
single argument:

In [10]: def doSomething(func):
    ....:     func("test")

In [12]: doSomething(o.method)
test

In summary:
Class.method => unbound method, call with instance as
first arg
instance.method => bound method, call with normal
argument list

Kent

_______________________________________________
Tutor maillist  -  Tutorpython.org
http://
mail.python.org/mailman/listinfo/tutor

Re: class methods as argument
country flaguser name
Netherlands
2007-02-10 06:56:49
Hi Thomas,


thomas coopman wrote:
<snip>
> I want to execute the class method given as argument,
> but this obvious doesn't work, but I don't know how to
> get it work,

Pass the method reference of the class as argument, like
this:

 >>> class A(object):
...     def __init__(self, x): self.x = x
...     def dostuff(self, arg):
...         print self.x
...         print arg
...
 >>> def dostuff(obj, method):
...     method(obj, 'blabla')
...
 >>> a = A(5)
 >>> dostuff(a, A.dostuff)
5 # this demonstates method has been called for instance a
blabla




Yours,

Andrei

_______________________________________________
Tutor maillist  -  Tutorpython.org
http://
mail.python.org/mailman/listinfo/tutor

Re: class methods as argument
user name
2007-02-10 09:32:33
On Sat, 10 Feb 2007 07:55:54 -0500
Kent Johnson <kent37tds.net> wrote:

> thomas coopman wrote:
> > Hi,
> > 
> > I want to do something like this, don't know how
to properly
> > explain it, so I just give you some example code
> > 
> >>>> class Foo(object):
> >>>> 	def method(self, arg):
> >>>> 		print arg
> > 
> >>>> def doSomething(object, func):
> >>>> 	object.func("test")
> > 
> >>>> object = Foo()
> >>>> doSomething(object, Foo.method)
> > 
> > I want to execute the class method given as
argument,
> > but this obvious doesn't work, but I don't know
how to
> > get it work,
> 
> First a quick note - don't use object as a parameter or
variable
> name, it will hide the definition of the built-in
object class.
Yes, I know, it was a bad example
> 
> You are very close. Foo.method is called an 'unbound
method' of class 
> Foo. The syntax for calling an unbound method is to
pass a class 
> instance as the first argument, followed by the actual
argument list.
> It is actually the same argument list that you use when
you declare
> the function (starting with self).
> 
> So your example can be written this way:
> 
> In [4]: class Foo(object):
>     ...:     def method(self, arg):
>     ...:         print arg
> 
> In [6]: o=Foo()
> 
> In [8]: def doSomething(obj, func):
>     ...:     func(obj, "test")
> 
> In [9]: doSomething(o, Foo.method)
> test
> 
> 
> A more common way to do this is to use a 'bound
method'. That is what 
> you get when you refer to instance.method instead of
Class.method. A 
> bound method includes a reference to the particular
instance and can
> be called like an ordinary function. Rather than
passing the instance
> and the unbound method to doSomething(), just pass the
bound method
> as a single argument:
> 

> In [10]: def doSomething(func):
>     ....:     func("test")
> 
> In [12]: doSomething(o.method)
> test
> 
> In summary:
> Class.method => unbound method, call with instance
as first arg
> instance.method => bound method, call with normal
argument list
> 
> Kent
> 

Thank you for the explanation of bound and unbound methods.
I understand that it is more common to use a bound method,
but I don't
think that I can use this because at the time I save the
method, I don't
know anything about the instances.

I use this for making a sorted list using any method you
give as
argument when you create the list.  This class only gets to
know it's
instances when you add them.

In [3]: class SortedList(object):
   ...:     def __init__(self, compare):
   ...:         self.compare = compare
   ...:     def __add_(self, object):
   ...:         for i in self.data:
   ...:             self.compare(object, i)
   ...:

In [4]: class FooList(SortedList):
   ...:     def __init__(self):
   ...:         self.compare = Foo.compare


__add__ doesn't do anything here of course, it is just an
example,
but I don't think that I can use a bound method in this
case?

also,
Is it better to use super in FooList? and how should I use
it then?

Thomas
_______________________________________________
Tutor maillist  -  Tutorpython.org
http://
mail.python.org/mailman/listinfo/tutor

Re: class methods as argument
user name
2007-02-10 12:24:05
On Sat, 10 Feb 2007 09:04:15 -0500
Kent Johnson <kent37tds.net> wrote:

> thomas coopman wrote:
> > 
> > also,
> > Is it better to use super in FooList? and how
should I use it then?
> 
> Actually I would say that FooList is not pulling its
weight.
> SortedList already allows specialization by the compare
function, so
> to create the equivalent of a FooList you just call
> SortedList(Foo.compare).
I know that in this example it's rather useless to create
FooList, but
the subclasses I have of SortedList have other
specializations so I
will keep using them.

> 
> If you do want to keep FooList then you should call 
> SortedList.__init__() to set the compare function.
> SortedList.__init__ is an unbound function so you call
it like this:
>    SortedList.__init__(self, Foo.compare)
This works.
I think I'll need to reed some more about super because I
thought I had
to use super in this case.

> 
> Another design you might want to consider - if you will
always be 
> sorting each type of list by the same compare method -
is to define a 
> __cmp__() method in each class that will be part of a
SortedList and
> use plain comparison operators (< > etc) to do
the compare.
That's the problem.  I define for most of my classes a
__cmp__() method
but, some classes have another way of being sorted, and
that's why I
give the compare method as an argument in SortedList

> 
> Finally note that Python's sort() function is very fast
and flexible
> and it might be better just to sort the list when you
need it to be
> sorted, rather than keeping it sorted. Or maybe what
you really need
> is a heap (see the heapq module). If you really want to
keep a sorted
> list, you should look at the bisect module, it might
help.
I now use sort() when there is some data initially.  After
creation, I
insert data with my own bisect method, I also use it to
search the data.

I mostly need the sorted list, because I want to detect when
a object
is added with the same value of some item in the list and
take
appropriate actions.

> 
> Kent
> 

Thomas
_______________________________________________
Tutor maillist  -  Tutorpython.org
http://
mail.python.org/mailman/listinfo/tutor

[1-6]

about | contact  Other archives ( Real Estate discussion Medical topics )