Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

class or instance method

10 views
Skip to first unread message

Paul Johnston

unread,
Jun 17, 2009, 6:09:34 AM6/17/09
to
Hi,

I would like to have a method that is both a classmethod and an
instancemethod. So:

class MyClass(object):
@class_or_instance
def myfunc(cls_or_self):
pass

The semantics I'd like are:
When you call MyClass.myfunc, it gets passed a class
When you call MyClass().myfunc, it gets passed an instance

I'm sure I've seen some code to do this somewhere, but I can't find it
now. Any help appreciated.

Paul

Bruno Desthuilliers

unread,
Jun 17, 2009, 6:39:47 AM6/17/09
to
Paul Johnston a �crit :

IIRC, there's something quite similar in formencode.

Hrvoje Niksic

unread,
Jun 17, 2009, 8:40:45 AM6/17/09
to
Paul Johnston <paul...@gmail.com> writes:

> I would like to have a method that is both a classmethod and an
> instancemethod. So:
>
> class MyClass(object):
> @class_or_instance
> def myfunc(cls_or_self):
> pass
>
> The semantics I'd like are:
> When you call MyClass.myfunc, it gets passed a class
> When you call MyClass().myfunc, it gets passed an instance

class class_or_instance(object):
def __init__(self, fn):
self.fn = fn
def __get__(self, obj, cls):
if obj is not None:
return lambda *args, **kwds: self.fn(obj, *args, **kwds)
else:
return lambda *args, **kwds: self.fn(cls, *args, **kwds)

>>> class MyClass(object):
... @class_or_instance
... def myfunc(cls_or_self):
... return cls_or_self
...
>>> MyClass.myfunc()
<class '__main__.MyClass'>
>>> MyClass().myfunc()
<__main__.MyClass object at 0xb7a248cc>

You might want to use functools.wrap to return named functions rather
than unnamed lambdas, but you get the idea.

Paul Johnston

unread,
Jun 21, 2009, 9:31:58 AM6/21/09
to
Hi,

> class class_or_instance(object):
>     def __init__(self, fn):

...

This works a treat, thank-you.

Paul

Scott David Daniels

unread,
Jun 21, 2009, 5:23:41 PM6/21/09
to
Hrvoje Niksic wrote:
> ...

> class class_or_instance(object):
> def __init__(self, fn):
> self.fn = fn
> def __get__(self, obj, cls):
> if obj is not None:
> return lambda *args, **kwds: self.fn(obj, *args, **kwds)
> else:
> return lambda *args, **kwds: self.fn(cls, *args, **kwds)
> ...

Just to polish a bit:

import functools

class ClassOrInstance(object):
def __init__(self, fn):
self._function = fn
self._wrapper = functools.wraps(fn)

def __get__(self, obj, cls):
return self._wrapper(functools.partial(self._function,
cls if obj is None else obj))


--Scott David Daniels
Scott....@Acm.Org

Miles Kaufmann

unread,
Jun 21, 2009, 5:56:01 PM6/21/09
to pytho...@python.org

from types import MethodType

class ClassOrInstance(object):
def __init__(self, func):
self._func = func

def __get__(self, obj, cls):
return MethodType(self._func, cls if obj is None else obj, cls)


-Miles

0 new messages