Last active
August 29, 2015 14:04
-
-
Save rbistolfi/7883392d6ba9c45fc4fa to your computer and use it in GitHub Desktop.
Python class and instance methods that can share a name
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
"""Instance and class methods that can share a name""" | |
class DualMethod(object): | |
"""A method that can be called as instance method and as class method | |
>>> class Test(object): | |
... | |
... @dualmethod | |
... def spam(self): | |
... print "I am an instance method" | |
... | |
... @spam.classmethod | |
... def spam(cls): | |
... print "I am a class method" | |
... | |
... | |
>>> Test.spam() | |
I am a class method | |
>>> Test().spam() | |
I am an instance method | |
""" | |
def __init__(self, instancemethod, classmethod=None): | |
self.instancemethod = instancemethod | |
self._classmethod = classmethod | |
def __get__(self, obj, type=None): | |
""" | |
Return instancemethod if there is an instance. If there is no instance | |
and there is a type, return classmethod instead | |
""" | |
if obj: | |
return self.instancemethod.__get__(obj) | |
if type: | |
return self._classmethod.__get__(type) | |
raise TypeError("Invalid dualmethod") | |
def classmethod(self, func): | |
"setter for class methods" | |
self._classmethod = func | |
return self | |
def dualmethod(func): | |
"Convenient decorator" | |
return DualMethod(func) | |
if __name__ == "__main__": | |
import unittest | |
class DualMethodTestCase(unittest.TestCase): | |
def test_dualmethod(self): | |
class Test(object): | |
@dualmethod | |
def spam(self): | |
return self | |
@spam.classmethod | |
def spam(cls): | |
return cls | |
instance = Test() | |
self.assertIs(instance.spam(), instance) | |
self.assertIs(Test.spam(), Test) | |
unittest.main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment