Why use a classmethod over an Instance method in python
Question:
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
Answers:
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.
@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
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.
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(some_deets)
mel.who_are_you() # Hello Melissa, you are 32 years old
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
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.
@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
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.
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(some_deets)
mel.who_are_you() # Hello Melissa, you are 32 years old