I'm wondering if it's possible to make a method which behaves differently when called as a class method than when called as an instance method.
For example, as a skills-improvement project, I'm writing a Matrix
class (yes, I know there are perfectly good matrix classes already out there). I've created a class method for it called identity
which returns an identity matrix of a specified size.
Now, when called on an instance of Matrix
, it seems logical that the size shouldn't need to be specified; it should return an identity matrix of the same size as the Matrix
it's called on.
In other words, I'd like to define a method which can determine whether it was called via an instance and, if so, access that instance's attributes. Unfortunately, even after digging through the documentation and a few Google searches, I haven't found anything which suggests this is possible. Does anyone know differently?
Edit:
Wow! Clearly, I'm still not quite used to first-class functions. Here's what I ended up with — thanks to Unknown for providing the key!
class Foo(object): def __init__(self, bar): self.baz = bar self.bar = MethodType(lambda self: self.__class__.bar(self.baz), self, self.__class__) @classmethod def bar(cls, baz): return 5 * baz Foo.bar(3) # returns 15 foo = Foo(7) foo.bar() # returns 35
Edit 2:
Just a quick note — this technique (and most of those presented below) won't work on classes which define __slots__
, as you cannot reassign the method.
A class method is a method that's shared among all objects. To call a class method, put the class as the first argument. Class methods can be can be called from instances and from the class itself.
Key Takeaways. Instance methods need a class instance and can access the instance through self . Class methods don't need a class instance. They can't access the instance ( self ) but they have access to the class itself via cls .
The instance method acts on an object's attributes. It can modify the object state by changing the value of instance variables. Static methods have limited use because they don't have access to the attributes of an object (instance variables) and class attributes (class variables).
Questionably useful Python hacks are my forte.
from types import * class Foo(object): def __init__(self): self.bar = methodize(bar, self) self.baz = 999 @classmethod def bar(cls, baz): return 2 * baz def methodize(func, instance): return MethodType(func, instance, instance.__class__) def bar(self): return 4*self.baz >>> Foo.bar(5) 10 >>> a=Foo() >>> a.bar() 3996
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With