What Is the Purpose of Class Methods

What is the purpose of class methods?

Class methods are for when you need to have methods that aren't specific to any particular instance, but still involve the class in some way. The most interesting thing about them is that they can be overridden by subclasses, something that's simply not possible in Java's static methods or Python's module-level functions.

If you have a class MyClass, and a module-level function that operates on MyClass (factory, dependency injection stub, etc), make it a classmethod. Then it'll be available to subclasses.

what is the use and when to use @classmethod in python?

There are 3 kinds of methods in python:

  • Instance method
  • Class method
  • Static Method
class Person():
species='homo_sapiens' # This is class variable
def __init__(self, name, age):
self.name = name # This is instance variable
self.age = age

def show(self):
print('Name: {}, age: {}.'.format(self.name, date.today().year - self.age))

@classmethod
def create_with_birth_year(cls, name, birth_year):
return cls(name, date.today().year - birth_year)

@classmethod
def print_species(cls):
print('species: {}'.format(cls.species))

@staticmethod
def get_birth_year(age):
return date.today().year - age

class Teacher(Person):
pass

1) Instance method (show) need an instance and must use self as the first parameter. It can access the instance through self and influence the state of an instance.

2) Class method (create_with_birth_year and print_species) need no instance and use cls to access the class and influence the state of a class. We can use @classmethod to make a factory, such as:

navy = Person.create_with_birth_year('Navy Cheng', 1989)
navy.show()

and this factory can be inherited:

zhang = Teacher.create_with_birth_year('zhang', 1980)
print(type(zhang))

and class method can be used access class variable:

Person.print_species()

3) Static Method (get_birth_year) need no special parameter(self or cls) and will change any state of a class or instance. It can privde some helper function about a class.

When should I use @classmethod and when def method(self)?

Your guess is correct - you understand how classmethods work.

The why is that these methods can be called both on an instance OR on the class (in both cases, the class object will be passed as the first argument):

class Dummy(object):

@classmethod
def some_function(cls,*args,**kwargs):
print cls

#both of these will have exactly the same effect
Dummy.some_function()
Dummy().some_function()

On the use of these on instances: There are at least two main uses for calling a classmethod on an instance:

  1. self.some_function() will call the version of some_function on the actual type of self, rather than the class in which that call happens to appear (and won't need attention if the class is renamed); and
  2. In cases where some_function is necessary to implement some protocol, but is useful to call on the class object alone.

The difference with staticmethod: There is another way of defining methods that don't access instance data, called staticmethod. That creates a method which does not receive an implicit first argument at all; accordingly it won't be passed any information about the instance or class on which it was called.

In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1)

In [7]: Foo.some_static(1)
Out[7]: 2

In [8]: Foo().some_static(1)
Out[8]: 2

In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2)

In [10]: Bar.some_static(1)
Out[10]: 2

In [11]: Bar().some_static(1)
Out[11]: 2

The main use I've found for it is to adapt an existing function (which doesn't expect to receive a self) to be a method on a class (or object).

Purpose of Instance Methods vs. Class Methods in Objective-C

Generally speaking, you should create instance methods when you need code that operates on a specific instance of an object. You create a class method when you need to do something that involves that class in general but probably doesn't operate on any specific objects of that class.

In practice, you will find that nearly all of your methods should be instance methods. Just take a look at any existing Objective-C class like NSString, NSArray, UIView, etc. and you'll see that the vast majority of their methods are instance methods. The most common use of class methods (again, look at the classes I mentioned) are for convenience constructors that return autorelease objects, or singleton accessors.

Consider the length method in NSString. Why is this an instance method and not a class method? It is an instance method because it only makes sense to ask a specific instance of NSString what its length is. Asking NSString in general for a length (i.e. if length was a class method) wouldn't make any sense.

On the other hand, let's say that we want to add a method to NSNumber that will return the maximum integer value that can be stored on a given system. In this case, it should be a class method because we're just asking a general question of NSNumber that is independent of any specific instance.

Why use a classmethod over an Instance method in python

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, than 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.

Meaning of @classmethod and @staticmethod for beginner

Though classmethod and staticmethod are quite similar, there's a slight difference in usage for both entities: classmethod must have a reference to a class object as the first parameter, whereas staticmethod can have no parameters at all.

Example

class Date(object):

def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year

@classmethod
def from_string(cls, date_as_string):
day, month, year = map(int, date_as_string.split('-'))
date1 = cls(day, month, year)
return date1

@staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split('-'))
return day <= 31 and month <= 12 and year <= 3999

date2 = Date.from_string('11-09-2012')
is_date = Date.is_date_valid('11-09-2012')

Explanation

Let's assume an example of a class, dealing with date information (this will be our boilerplate):

class Date(object):

def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year

This class obviously could be used to store information about certain dates (without timezone information; let's assume all dates are presented in UTC).

Here we have __init__, a typical initializer of Python class instances, which receives arguments as a typical instance method, having the first non-optional argument (self) that holds a reference to a newly created instance.

Class Method

We have some tasks that can be nicely done using classmethods.

Let's assume that we want to create a lot of Date class instances having date information coming from an outer source encoded as a string with format 'dd-mm-yyyy'. Suppose we have to do this in different places in the source code of our project.

So what we must do here is:

  1. Parse a string to receive day, month and year as three integer variables or a 3-item tuple consisting of that variable.
  2. Instantiate Date by passing those values to the initialization call.

This will look like:

day, month, year = map(int, string_date.split('-'))
date1 = Date(day, month, year)

For this purpose, C++ can implement such a feature with overloading, but Python lacks this overloading. Instead, we can use classmethod. Let's create another constructor.

    @classmethod
def from_string(cls, date_as_string):
day, month, year = map(int, date_as_string.split('-'))
date1 = cls(day, month, year)
return date1

date2 = Date.from_string('11-09-2012')

Let's look more carefully at the above implementation, and review what advantages we have here:

  1. We've implemented date string parsing in one place and it's reusable now.
  2. Encapsulation works fine here (if you think that you could implement string parsing as a single function elsewhere, this solution fits the OOP paradigm far better).
  3. cls is the class itself, not an instance of the class. It's pretty cool because if we inherit our Date class, all children will have from_string defined also.

Static method

What about staticmethod? It's pretty similar to classmethod but doesn't take any obligatory parameters (like a class method or instance method does).

Let's look at the next use case.

We have a date string that we want to validate somehow. This task is also logically bound to the Date class we've used so far, but doesn't require instantiation of it.

Here is where staticmethod can be useful. Let's look at the next piece of code:

    @staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split('-'))
return day <= 31 and month <= 12 and year <= 3999

# usage:
is_date = Date.is_date_valid('11-09-2012')

So, as we can see from usage of staticmethod, we don't have any access to what the class is---it's basically just a function, called syntactically like a method, but without access to the object and its internals (fields and other methods), which classmethod does have.

Why should I use a classmethod in python?

If you see _randomize method, you are not using any instance variable (declared in init) in it but it is using a class var i.e. RANDOM_CHOICE = 'abcdefg'.

import random

class Randomize:
RANDOM_CHOICE = 'abcdefg'

def __init__(self, chars_num):
self.chars_num = chars_num

def _randomize(self, random_chars=3):
return ''.join(random.choice(self.RANDOM_CHOICE)
for _ in range(random_chars))

It means, your method can exist without being an instance method and you can call it directly on class.

  Randomize._randomize()

Now, the question comes does it have any advantages?

  • I guess yes, you don't have to go through creating an instance to use this method which will have an overhead.

    ran = Randomize() // Extra steps
    ran._randomize()

You can read more about class and instance variable here.

is there any advantage when use class method instead of instance method?

My explanation is a little different.

Instance methods are sent to an INSTANCE of a class. An instance of a class is a concrete thing. It has state data that persists for the life of the object. When you send a message to an object, it can use that state data to do things, and it can remember information for later.

Class methods are sent to the class as a whole. A class is a more abstract concept. Classes do not save state data, at least in Objective C (In other languages like C++, there are class variables that belong to the entire class, but Objective C does not have class variables.)

Lets move to an example of a car factory

The car factory is the class. The car class has a class method buildCar. The buildCar method takes parameters that tell what color the car should be, how big the engine should be, what options it should have, etc. You sent the car factory (the class) a buildCar message, and it creates and returns an instance of that class (the car factory builds you a car and gives it to you.)

Once you've created a car, that particular car has state variables that store things like the channel on the radio, the amount of gas left in the tank, the milage ("kilometerage"?) on the odometer, the wear level on the brakes, etc. Different cars will have different values for those variables.

You can ask an individual car how much gas is left in it's tank. (instance method.) Car A might have a full tank, and car B might be nearly empty.

However, it would not make sense to ask the car factory how much gas it has in the tank. A car factory doesn't have a gas tank. However, you could ask a car factory about the types of cars that it can build and the options for those cars. That is static information that always holds true for that car factory.

In addition to "factory methods" (e.g. build me a car), you can use class methods like you use functions in a procedural language. A class method is self-contained. You pass all the parameters into the method that you need in order to do whatever task is required, and you get back a single result (or no result for a void class method.) Once the class method is done executing, there is no state data left to record what happened.

What is the purpose of calling super class's method while overriding a method?

When you override a method, you redefine the method i.e. if this method is called on the instance of the child class (in which you have overridden the method), this new version of the definition will be called.

When you override a method (i.e. redefine or in other words, replace the superclass definition with the child's version of the definition), you have two choices:

  1. Do not use anything from the superclass definition and rewrite it in a completely new way.
  2. Reuse the superclass definition at some point (in the beginning/middle/end) in the new definition. It's like putting a cherry on the ice cream cone where ice cream cone is the superclass definition of the method and cherry is added in the new definition.

Note that as already pointed out by Andy Turner, a requirement to call super is considered an antipattern.



Related Topics



Leave a reply



Submit