substitution of a method by a callable object

N

netimen

Can I substitute a method of a class by a callable object (not a
function)? I can very easy insert my function in a class as a method,
but an object - can't.

I have the following:

class Foo(object):
pass

class Obj(object):
def __call__(self, obj_self):
print 'Obj'

def func(self):
print 'func'

f = Foo()
Foo.meth = func
f.meth() # all goes OK
Foo.meth = Obj()
f.meth() # I get TypeError: __call__() takes exactly 2 arguments (1
given)
 
B

Bruno Desthuilliers

netimen a écrit :
Can I substitute a method of a class by a callable object (not a
function)? I can very easy insert my function in a class as a method,
but an object - can't.

functions implement the descriptor protocol so when looked up as class
attributes, the lookup invoke their __get__ method, which in turn
returns a method object (which is a thin wrapper around the function,
the class and the instance).

You can either build the method manually (as Georges explained), or make
your own Obj class a proper descriptor:

from types import MethodType

class Obj(object):
__name__ = "Obj" # for Method.__repr_

def __call__(self, obj_self):
print 'Obj'

def __get__(self, instance, cls):
return MethodType(self, instance, cls)


HTH
 
T

Terry Reedy

netimen said:
Can I substitute a method of a class by a callable object (not a
function)? I can very easy insert my function in a class as a method,
but an object - can't.

Yes you can and did.
class Foo(object):
pass

class Obj(object):
def __call__(self, obj_self):
print 'Obj'

def func(self):
print 'func'

f = Foo()
Foo.meth = func
f.meth() # all goes OK
Foo.meth = Obj()
f.meth() # I get TypeError: __call__() takes exactly 2 arguments (1
given)

So either remove the unused obj_self parameter from __call__ or pass
something -- anything -- to be bound to it.
f.meth(1) for instance, works fime (in 3.0 at least)
 
G

George Sakkis

Can I substitute a method of a class by a callable object (not a
function)? I can very easy insert my function in a class as a method,
but an object - can't.

I have the following:

class Foo(object):
    pass

class Obj(object):
    def __call__(self, obj_self):
        print 'Obj'

def func(self):
    print 'func'

f = Foo()
Foo.meth = func
f.meth() # all goes OK
Foo.meth = Obj()
f.meth() # I get TypeError: __call__() takes exactly 2 arguments (1
given)

You have to wrap it as an (unbound) instance method explicitly:

from types import MethodType
Foo.meth = MethodType(Obj(), None, Foo)
f.meth()

For normal functions this seems to be done implicitly (of course you
can do it explicitly if you want):
<unbound method Foo.func>

George
 
N

netimen

netimen a ¨¦crit :


functions implement the descriptor protocol so when looked up as class
attributes, the lookup invoke their __get__ method, which in turn
returns a method object (which is a thin wrapper around the function,
the class and the instance).

You can either build the method manually (as Georges explained), or make
your own Obj class a proper descriptor:

from types import MethodType

class Obj(object):
__name__ = "Obj" # for Method.__repr_

def __call__(self, obj_self):
print 'Obj'

def __get__(self, instance, cls):
return MethodType(self, instance, cls)

HTH

thanks!
 
B

Bruno Desthuilliers

netimen a écrit :
(snip)
OK, I have implemented Bruno Desthuilliers example. But there is
another question: can I having a method determine if it is an instance
of given class. So:

As the name imply, a method is usually, well, an instance of type
'method' !-)
class Obj(object): (snip)

class Foo(object):
pass

Foo.meth = Obj()

## in some another place of code
if isinstance(Foo.meth, Obj): # doesn't work because type(Foo.meth) is
now 'instancemethod'

Indeed. I suppose what you want is to know if the callable wrapped by
the method is an instance of Obj ?
Can I determine that?

Yeps. Test the im_func attribute of the method:

if isinstance(Foo.meth.im_func, Obj): print "yadda"

But you'd better put this in a try/except block, because a callable
attribute of a class is not necessarily a method - and so it may not
have an im_func attribute.

Also, may I ask why you want to check this ? Not that it's necessarily
wrong, but real use case for typechecking are pretty rare.
 
T

Terry Reedy

George said:
You have to wrap it as an (unbound) instance method explicitly:

Nope. As the error message says, the method was called with nothing
provided to be bound to the extraneous parameter obj_self. Either
provide an arg, such as with f.meth(1), *or* delete obj_self and 'Obj'
is printed, with both 2.5 and 3.0.
 
N

netimen

Nope. šAs the error message says, the method was called with nothing
provided to be bound to the extraneous parameter obj_self. šEither
provide an arg, such as with f.meth(1), *or* delete obj_self and 'Obj'
is printed, with both 2.5 and 3.0.

OK, I have implemented Bruno Desthuilliers example. But there is
another question: can I having a method determine if it is an instance
of given class. So:

class Obj(object):
__name__ = "Obj" # for Method.__repr_

def __call__(self, obj_self):
print 'Obj'

def __get__(self, instance, cls):
return MethodType(self, instance, cls)

class Foo(object):
pass

Foo.meth = Obj()

## in some another place of code
if isinstance(Foo.meth, Obj): # doesn't work because type(Foo.meth) is
now 'instancemethod'
...

Can I determine that?
 
N

netimen

netimen a ¨¦crit :
(snip)


As the name imply, a method is usually, well, an instance of type
'method' !-)






Indeed. I suppose what you want is to know if the callable wrapped by
the method is an instance of Obj ?




Yeps. Test the im_func attribute of the method:

if isinstance(Foo.meth.im_func, Obj): print "yadda"

But you'd better put this in a try/except block, because a callable
attribute of a class is not necessarily a method - and so it may not
have an im_func attribute.

Also, may I ask why you want to check this ? Not that it's necessarily
wrong, but real use case for typechecking are pretty rare.

Thanks! I have wasted much time playing with different Foo.meth trying
to get to Obj through them. But im_func was one of the fields I
haven't checked )

Indeed, I have managed already without that. The task was to
substitute __str__ method by a complex formatter. It called a low-
level formatter, a function wich returned simple str(self). That
function could be called with objects with substituted formatters and
with simple objects. So to avoid recursion I wanted to check wether
the formatter of my object was substituted.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,042
Latest member
icassiem

Latest Threads

Top