I have a class that in principle carries all the information about it in its class body. When instantiated, it receives additional information that together with the class attributes forms a regular instance. My problem now lies in the fact that I need to implement a method which should be called as class method when it is called from a class object but should be called as regular instance method when called from an instance:
e.g. something like
class MyClass(object):
attribs = 1, 2, 3
def myMethod(self, args):
if isclass(self):
"do class stuff"
else:
"do instance stuff"
MyClass.myMethod(2) #should now be called as a class method, e.g. I would normally do @classmethod
MyClass().myMethod(2) #should now be called as instance method
Of course I could declare it as staticmethod and pass either the instance or the class object explicitly, but that seems rather unpythonic and also user unfriendly.
2 Answers 2
If the methods are to behave differently, you could simply change which one is exposed by that name at initialization time:
class MyCrazyClass:
@classmethod
def magicmeth(cls):
print("I'm a class")
def _magicmeth(self):
print("I'm an instance")
def __init__(self):
self.magicmeth = self._magicmeth
8 Comments
Meter*Meter is as a Meter just as a Meter*Second -- namely not at all. If you model units like this, your unit system is broken.You can define a decorator that works like a regular method when called on an instance, or class method when called on a class. This requires a descriptor:
from functools import partial
class anymethod:
"""Transform a method into both a regular and class method"""
def __init__(self, call):
self.__wrapped__ = call
def __get__(self, instance, owner):
if instance is None: # called on class
return partial(self.__wrapped__, owner)
else: # called on instance
return partial(self.__wrapped__, instance)
class Foo:
@anymethod
def bar(first):
print(first)
Foo.bar() # <class '__main__.Foo'>
Foo().bar() # <__main__.Foo object at 0x106f86610>
Note that this behaviour will not be obvious to most programmers. Only use it if you really need it.
Comments
Explore related questions
See similar questions with these tags.
classmethod) the purpose of classmethods and regular methods is usually very different. Strongly consider whether the ease of calling one unified method outweighs the ease of knowing what each separate method does.