Re: Method behavior for user-created class instances
On Jul 15, 9:53 am, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> wrote: > On 15 juil, 01:24, [EMAIL PROTECTED] 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. > > You need to implement the descriptor protocol the same way the > function type do. > > import types > > class Foo(object): > def __call__(self, instance): > print "%s - %s" % (self, instance) > > def __get__(self, instance, cls): > return types.MethodType(self, instance, cls) > > class Bar(object): > foo = Foo() > > b = Bar() > b.foo() > > > 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. > > Extending types.FunctionType doesn't work OOTB (there's some > incompatibility wrt/ metaclasses) Thanks, this got me started in writing it for 3.0. There are no more unbound methods in 3.0, so a check for whether instance is None is necessary to give the right behavior. Here is the final implementation I came up with: from abc import ABCMeta, abstractmethod from functools import update_wrapper from types import MethodType class decorator(metaclass = ABCMeta): def __init__(self, function): update_wrapper(self, function) self.function = function def __get__(self, instance, cls): if instance is None: return self return MethodType(self, instance) @abstractmethod def __call__(): pass To use it, write a class that inherits decorator and overrides __call__, probably doing something with self.function. -- http://mail.python.org/mailman/listinfo/python-list
Re: Method behavior for user-created class instances
On 15 juil, 01:24, [EMAIL PROTECTED] 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. You need to implement the descriptor protocol the same way the function type do. import types class Foo(object): def __call__(self, instance): print "%s - %s" % (self, instance) def __get__(self, instance, cls): return types.MethodType(self, instance, cls) class Bar(object): foo = Foo() b = Bar() b.foo() > 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. Extending types.FunctionType doesn't work OOTB (there's some incompatibility wrt/ metaclasses) -- http://mail.python.org/mailman/listinfo/python-list
Re: Method behavior for user-created class instances
On Jul 14, 9:04 pm, Larry Bates <[EMAIL PROTECTED]> wrote: > [EMAIL PROTECTED] 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__(). -- http://mail.python.org/mailman/listinfo/python-list
Re: Method behavior for user-created class instances
[EMAIL PROTECTED] 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 -- http://mail.python.org/mailman/listinfo/python-list