Google 网上论坛不再支持新的 Usenet 帖子或订阅项。历史内容仍可供查看。

class or instance method

已查看 3 次
跳至第一个未读帖子

Paul Johnston

未读,
2009年6月17日 06:09:342009/6/17
收件人
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

未读,
2009年6月17日 06:39:472009/6/17
收件人
Paul Johnston a �crit :

IIRC, there's something quite similar in formencode.

Hrvoje Niksic

未读,
2009年6月17日 08:40:452009/6/17
收件人
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

未读,
2009年6月21日 09:31:582009/6/21
收件人
Hi,

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

...

This works a treat, thank-you.

Paul

Scott David Daniels

未读,
2009年6月21日 17:23:412009/6/21
收件人
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

未读,
2009年6月21日 17:56:012009/6/21
收件人 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 个新帖子