11

I have been trying to get my head around classmethods for a while now. I know how they work but I don't understand why use them or not use them.

For example:

I know i can use an instance method like this:

class MyClass():
    def __init__(self):
        self.name = 'Chris'
        self.age = 27

    def who_are_you(self):
        print('Hello {}, you are {} years old'.format(self.name, self.age))

c = MyClass()
c.who_are_you()

I also know that by using the classmethod I can call the who_are_you() without creating an instance of my class:

class MyClass():
    name = 'Chris'
    age = 27

    @classmethod
    def who_are_you(cls):
        print('Hello {}, you are {} years old'.format(cls.name, cls.age))

MyClass.who_are_you()

I don't get why you would pick one method over the other

6
  • You use an instance method when you have instance variables. With the class method, you can't have different instances with a different age or name Commented Feb 28, 2016 at 18:31
  • 1
    see: stackoverflow.com/questions/12179271/… Commented Feb 28, 2016 at 18:32
  • 2
    You usually don't create a class to represent a person. Usually, you create a class Person, and create instance of it to represent a person. Commented Feb 28, 2016 at 18:32
  • 2
    Possible duplicate of When should I use @classmethod and when def method(self)? Commented Feb 28, 2016 at 18:32
  • 2
    Along with what Ginger said, you pass in Chris and 27 into the constructor of the Person class, not hard code them into the class Commented Feb 28, 2016 at 18:35

4 Answers 4

23

In your second example, you've hard-coded the name and age into the class. If name and age are indeed properties of the class and not a specific instance of the class, then using a class method makes sense. However, if your class was something like Human of which there are many instances with different names and ages, then it wouldn't be possible to create a class method to access the unique names and ages of the specific instance. In that case, you would want to use an instance method.

In general:

  • If you want to access a property of a class as a whole, and not the property of a specific instance of that class, use a class method.
  • If you want to access/modify a property associated with a specific instance of the class, then you will want to use an instance method.
Sign up to request clarification or add additional context in comments.

1 Comment

I have been looking at many examples of classmethod and your explanation was the first that made sense to me. Thank you
5

Class methods are called when you don't have, or don't need, or can't have, an instance. Sometimes, a class can serve as a singleton when used this way. But probably the most common use of class methods is as a non-standard constructor.

For example, the Python dict class has a non-standard constructor called dict.fromkeys(seq, [value]). Clearly, there can be no instance involved - the whole point is to create an instance. But it's not the standard __init__() constructor, because it takes data in a slightly different format.

There are similar methods in the standard library: int.from_bytes, bytes.fromhex and bytearray.fromhex() and float.fromhex().

If you think about the Unix standard library, the fdopen function is a similar idea - it constructs a file from a descriptor, instead of a string path. Python's open() will accept file handles instead of paths, so it doesn't need a separate constructor. But the concept is more common than you might suspect.

Comments

0

@classmethod declares that method is static, therefore you could use it without creating new instance of class. One the other hand, in first example you have to create instance before youcould use method. Static methods are very useful for controllers in MVC pattern, etc, while nonstatic methods are used in models. More about @classmethod and @staticmethod here https://stackoverflow.com/a/12179752/5564059

1 Comment

This is not quite right. @classmethods are not the same as static methods. I understand you probably don't mean "the same as @staticmethod", but it's still not a good way to explain it. Also, models should not have methods!!! Simply because models are, well... just models. A model should not "do something"; therefore, it should not have methods. Maybe in a small or test app, this might be okay. But don't do this in corporate or large projects. It's a bad practice, conceptually wrong, and indicates poor project design, which will likely become harder to maintain.
0

To illustrate SPKoder and aghast's answers, let's make a sensible version of your class called Person. We'll make __init__ take their name and age, and add an alternate constructor that lets us pass the data in another form -- let's say a dict called deets that may contain various other fields.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def who_are_you(self):
        print('Hello {}, you are {} years old'.format(self.name, self.age))

    @classmethod
    def from_deets(cls, deets):
        name = deets['name']
        age = deets['age']
        return cls(name, age)

Example usage:

steve = Person('Stephen', 27)
steve.who_are_you()  # -> Hello Stephen, you are 27 years old

mels_deets = {'name': 'Melissa', 'age': 32, 'location': 'Ottawa'}
mel = Person.from_deets(mels_deets)
mel.who_are_you()  # Hello Melissa, you are 32 years old

Comments

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.