1

I have been lurking SO a long time and it happens that now it's my first time to ask a question since I couldn't find answer anywhere. I really hope that the title is not that confusing, I don't know how else to name it.

I am working on a Matrix class which I need for my college project (LUP decomposition, matrix inverse, solving linear equations...). Basic matrix operations, operator overloading, some helper methods, nothing too fancy.

As I was writing the code I came up with something that bothers me. I have a private method _makeMatrix. That method creates intended Matrix object. Then, I have classmethods like createFromList and createFromFile and similar, basically methods that allow a different way to create Matrix object. All of these methods call _makeMatrix to actually create Matrix object.

So, my question is, what is the difference between these two, except that in second case I can call _makeMatrix without creating object (which I obviously don't want to because _makeMatrix is intended to be private):

def _makeMatrix(r):
    # some code that creates Matrix object m
    return m

@classmethod
def createFromList(cls, matxList)
    # code that makes matxList suitable for passing to _makeMatrix()
    r = matxList
    return Matrix._makeMatrix(r)

and

@classmethod
def _makeMatrix(cls, r):
    # some code that creates Matrix object m
    return m

@classmethod
def createFromList(cls, matxList)
    # code that makes matxList suitable for passing to _makeMatrix()
    r = matxList
    return cls._makeMatrix(r)

What are the exact differences between these two and are there any benefits/drawbacks of using one or another approach?

6
  • On both codes you may write c._makeMatrix(r). BTW, the correct name for this object per PEP-8 is cls Commented Oct 14, 2015 at 0:53
  • What is _makeMatrix in the first case? Instance or Static method? Instance Method would need self as 1st argument. Static method would need a decorator. Commented Oct 14, 2015 at 4:46
  • @JBernardo Thx, I didn't know PEP-8 defines that too.; @sureshvv Yes, you are right, I missed that, self should be there. I've edited my code to address that. Commented Oct 14, 2015 at 8:25
  • @dosvarog Now your code doesn't work... You will be missing an argument when you call Matrix._makeMatrix(r) Commented Oct 14, 2015 at 14:07
  • @JBernardo Yes, you are right. I was on mobile phone so I didn't have my code in front of me. My original code was without self, like your third example. I haven't realized that before, so what is going on here? Does Python implicitly treat that method as a static one, even though I didn't decorate it with @staticmethod? If I put self in _makeMatrix method, I have to call it with cls._makeMatrix(cls, r), so I'm guessing there is also no difference between all these calls like in the previous examples? All this is a bit confusing, I have to admit. Commented Oct 14, 2015 at 18:54

1 Answer 1

2

The proper decorator for this example should be staticmethod. Here's why:

class MyClass:
    @classmethod
    def foo(cls, arg):
        # Here I can reference the class to work on things related to it
        # even if it is being accessed by an object of this class 
        pass


    @staticmethod
    def bar(arg):
        # This one behaves as a pure function unaware of the class it is
        # located on; even if it is accessed by an object of this class
        pass


    def baz(arg):
        # This one is tricky. Because it has no "self", it should crash
        # when accessed by an object of the class but not on the class
        # itself!
        pass

Testing:

x = MyClass()
x.foo(10) # OK, but `cls` is unused
x.bar(10) # OK!
x.baz(10) # Crash!!

MyClass.foo(10) # Ok, but `cls` is unused
MyClass.bar(10) # OK!
MyClass.baz(10) # OK!

So, whenever you need a "pure" function inside a class, i.e. a function which doesn't need any information from the class it is inserted this should be a staticmethod. If you don't want to instantiate an object but require some information from the class, you want classmethod.

Sign up to request clarification or add additional context in comments.

2 Comments

Generally, I agree with you, but this doesn't quite answer my question. What I really want to know is, what is the difference between defining _makeMatrix as classmethod and calling it from createFromList like cls._makeMatrix or leaving it as instance (regular) method and calling it from createFromList like Matrix._makeMatrix? What is difference between these two calls? Is it just semantics or is Python internally doing something different?
@dosvarog There is no difference whatsoever because in this context cls is Matrix. But it is always better to write cls (so your subclasses can work too)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.