A class method which behaves differently when called as an instance method?


A class method which behaves differently when called as an instance method?



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.




C# - To use Partial Classes, or Seperate Ones? [duplicate]

1:



php5 extend main class and use statics
Questionably useful Python hacks are my forte..
Call pure virtual function from parent class
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 


Should I refactor static nested classes in Java into separate classes?


Complexity class

2:



Can I instantiate a PHP class inside another class?
@Unknown What's the difference between your's and this:.
some kind off variable problem within php class
class Foo(object):      def _bar(self, baz):         print "_bar, baz:", baz      def __init__(self, bar):         self.bar = self._bar         self.baz = bar      @classmethod     def bar(cls, baz):         print "bar, baz:", baz  In [1]: import foo  In [2]: f = foo.Foo(42)  In [3]: f.bar(1) _bar, baz: 1  In [4]: foo.Foo.bar(1) bar, baz: 1  In [5]: f.__class__.bar(1) bar, baz: 1 


What term is used to describe when two classes depend on each other?

3:


[edited: use attribute to be a more direct answer; see the helpful comment by John Fouhy]. You can use a descriptor to do what you want:.
class cls_or_inst_method(object):     def __init__(self, class_method, instance_method):         self.class_method = class_method         self.instance_method = instance_method      def __get__(self, obj, objtype):         if obj is None:             return self.class_method         else:             return lambda: self.instance_method(obj)  def my_class_method(baz):     return baz + 1  def my_instance_method(self):     return self.baz * 2  class Foo(object):     baz = 10     bar = cls_or_inst_method(my_class_method, my_instance_method) 
Using the above:.
>>> print Foo.bar(5) 6 >>> my_foo = Foo() >>> print my_foo.bar() 20 


4:


I think the larger problem is that you are overloading the name 'bar' on class 'Foo', something python doesn't allow.

The second definition of 'bar' clobbers the first definition of 'bar'.

. Try to think of unique names for your classmethod and instance method.

i.e..
@classmethod def create(cls, baz):    ... 

def rubber_stamp(self): ...



5:


You can reassign your identity method in init with short lambda function:.
class Matrix(object):     def __init__(self):         self.identity = lambda s=self:s.__class__.identity(s)          #...whatever initialization code you have... 

self.size = 10 @classmethod def identity(self, other): #...always do you matrix calculations on 'other', not 'self'...

return other.size m = Matrix() print m.identity() print Matrix.identity(m)
If you're not familiar with lambda, it creates an anonymous function.

It's rarely necessary, but it can make your code more concise.

The lambda line above could be rewritten:.
    def identity(self):         self.__class__.indentity(self)     self.identity = identity 



70 out of 100 based on 50 user ratings 850 reviews