Method behavior for user-created class instances
crazychimp132 at gmail.com
crazychimp132 at gmail.com
Mon Jul 14 23:21:37 EDT 2008
On Jul 14, 9:04 pm, Larry Bates <larry.ba... at websafe.com`> wrote:
> crazychimp... at gmail.com wrote:
> > Greetings.
>
> > I am looking for a way to achieve method behavior for a class I
> > created. That is, it has a __call__ method, so can be called like a
> > function. But I also want it to be treated as a method when it appears
> > in a class body.
>
> > Eg.
>
> > class foo:
> > def __call__(self, inst): pass
>
> > class bar:
> > meth = foo()
>
> > such that bar().meth() will not raise an exception for too few
> > arguments (because the inst argument in foo.__call__ is implicitly set
> > to the bar instance). I know this has to do with writing the __get__
> > method of foo, but I am wondering if there is perhaps some class I can
> > just inherit from to get the proper __get__, which behaves identically
> > to that of regular Python functions. The need for this arises out of
> > the implementation of a function decorator as a class.
>
> > Thanks.
>
> While it is not clear "why" you would want this, I believe this works.
> If not, take a look at staticmethods or classmethods, they might work for you.
>
> >>> class foo(object):
> ... def __call__(self, inst):
> ... print "foo.__call__", inst
> ...
>
> >>> class bar:
> ... def __init__(self):
> ... self.foo = foo()
> ... self.meth = self.foo.__call__
> ...
> >>> b = bar()
> >>> b.meth(1)
> foo.__call__ 1
>
> -Larry
This doesn't work for me. I have a class which is used to decorate
functions, returning a callable object in the place of the original
function. So, instances of this class must be able to be used anywhere
a function would be used, and this means getting method behavior when
it is used in a class body.
A working implementation would be (in 3.0):
from functools import partial
from abc import ABCMeta, abstractmethod
class method_behavior(metaclass = ABCMeta):
def __get__(self, instance, owner):
if instance is None:
return self.__call__
return partial(self.__call__, instance)
@abstractmethod
def __call__(): pass
Then, any decorator class can inherit from it:
class foo(method_behavior):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwds):
print("calling decorated func")
return self.func(*args, **kwds)
Then, we can decorate a function with foo (via @foo) and it will work
either inside a class body or outside, it works everywhere an
undecorated function would work, eg.:
@foo
def bar():
print('bar')
class baz:
@foo
def bar(self):
print('bar')
What I am asking is whether there is a way to directly inherit method
behavior, instead of inexactly rewriting it as I did in
method_behavior.__get__().
More information about the Python-list
mailing list