I was looking for a way to have a method that when called on a class would get the class as its first argument, and when called on an instance would get that instance. Here is a nice way to do this (curry implementation thanks to http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/222061)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # from recipe 222061
curry = lambda func, *args, **kw:\
lambda *p, **n:\
func(*args + p, **dict(kw.items() + n.items()))
# bothmethod as a descriptor/decorator
class bothmethod(object):
def __init__(self, func):
self.func = func
def __get__(self, obj, type=None):
if obj is None:
return curry(self.func, type)
else:
return curry(self.func, obj)
# test
class Test(object):
@bothmethod
def method(self_or_cls):
print 'The first argument is: %s' % self_or_cls
# when called on the class, it gets the class
>>> Test.method()
The first argument is: <class '__main__.Test'>
# when called on an instance, it gets that instance
>>> Test().method()
The first argument is: <__main__.Test object at 0xb7d5ad0c>
|
Another way to do this would be to have a __hidden_method, have public_method = classmethod(__hidden_method) in the class, and set public_method = __hidden_method in __init__. This solution isn't very clean though, while this decorator is reusable :-)