Sunday, May 29, 2016

Introduce Python Classmethod and Staticmethod

classstatic

Normal Method

An simple way to use class in file cst_tuto.py

class tt(object):

    def __init__(self):
        print 'into init'
        self.a = 10

    def normethod(self):
        print 'in normal method'
        return 'L in normethod'

Adding the following lines at the end of the file, and execute it. ttt = tt() print ttt.normethod() You will get this result

root@ubuntu:# python cst_tuto.py
into init
in normal method
L in normethod

So simple, you have to declaim the class as a instance, ttt = tt().

But, is There a simple way to call normethod just like a class ? just like

tt.normethod()

The result is

root@ubuntu:# python cst_tuto.py
Traceback (most recent call last):
  File "cst_tuto.py", line 12, in <module>
    print tt.normethod()
TypeError: unbound method normethod() must be called with tt instance as first argument (got nothing instead)

It's not working.
Same question, we now ask again is there a simpole way to call normethod just like a class ? Yes, we can use staticmethod or classmethod. And I will show you what is the difference between them.

Staticmethod

Now we can modify cst_tuto.py as the followed.

class tt(object):

    def __init__(self):
        print 'into init'
        self.a = 10

    @staticmethod
    def stamethod():
        print 'in static'
        return 'L in static'

    def normethod(self):
        print 'in normal method'
        return 'L in normethod'

We now execute it

ttt = tt()
## it will access __init__
print ttt.normethod()
print '-------------------'
print tt.stamethod()

The result is

root@ubuntu:# python cst_tuto.py
into init
in normal method
L in normethod
-------------------
in static
L in static

Yes, the result is satisfied our expectation that staticmethod can directly access the class, and no instance needed anymore.

ClassMethod

Based on the previous used file cst_tuto.py, we add classmethod in it.

class tt(object):

    def __init__(self):
        print 'into init'
        self.a = 10

    @staticmethod
    def stamethod():
        print 'in static'
        return 'L in static'

    @classmethod
    def klamethod(cls):
        print 'in klassmethod'
        print cls
        return 'L in klamethod'

    def testmethod(self):
        print 'in the test method'
        return 'L in testmethod'

    def normethod(self):
        print 'in normal method'
        return 'L in normethod'

In the end of this file, and execute this python file.

print tt.klamethod()

The result is

root@ubuntu:# python cst_tuto.py
in klassmethod
<class '__main__.tt'>
L in klamethod

Of course it is satisfied our expectation again.
But what is cls. This is the only different between staticmethod and classmethod.

difference between staticmethod and classmethod

The staticmethod is a class that one can access it as a class not a instance. The classmethod is the same with staticmethod on this point, but classmethod can access the whole class tt by using cls, that staticmethod cannot do it. Staticmethod will be isolated and cannot contact to the other class.

The is an example that how the classmethod access the tt class. The hint is cls contains cls.__name__=tt that will help us to declaim the tt class.

class tt(object):

    def __init__(self):
        print 'into init'
        self.a = 10

    @staticmethod
    def stamethod():
        print 'in static'
        return 'L in static'

    @classmethod
    def klamethod(cls):
        print 'in klassmethod'
        ttt = cls()
        print ttt.testmethod()
        return 'L in klamethod'

    def testmethod(self):
        print 'in the test method'
        return 'L in testmethod'

    def normethod(self):
        print 'in normal method'
        return 'L in normethod'

print tt.klamethod()

Adding ttt=cls() that is equivlent to ttt=tt() but don't forget classmethod only have one way to connect to outside world that is cls.

The result is

root@ubuntu:~# python cst_tuto.py
in klassmethod
into init
in the test method
L in testmethod
L in klamethod

Yes, we can access testmethod in the tt class. It's perfect.

The other question is

how to access classmethod from a normal method

def normethod(self):
    # how to access klamethod
    tt.klamethod()
    print 'in normal method'
    return 'L in normethod'

You can access it just like the way to access classmethod.

how to access staticmethod from a classmethod

@classmethod
def klamethod(cls):
    print 'in klassmethod'
    print cls
    print 'use stamethod in klamethod'
    print cls.stamethod()

In class method you can access staitcmethod without declaim ttt=cls(), but using cls.stamethod(). Just like to access a staticmethod. But you cannot get init attibute, if you don't decliam it as a instance.

How to import them and the behavior of the staticmehtod and classmethod

Adding the file ii_tuto.py, but don't forget to create the file init.py.

from cst import tt as yy
yy.stamethod()
yy.klamethod()
s = yy()
s.testmethod()

yy.normethod()

We don't need to explain it too much, since it's similar to our explanation before.

More About Classmethod

As mentioned before, we emphisis the tt.__name__ is quite important concept using classmethod.

class Hero:

  @staticmethod
  def say_hello():
     print("Helllo...")

  @classmethod
  def say_class_hello(cls):
     if(cls.__name__=="HeroSon"):
        print("Hi Kido")
     elif(cls.__name__=="HeroDaughter"):
        cls.class1 = HeroDaughter()
        cls.class1.say_daughter_hello()
        print("Hi Princess")

class HeroSon(Hero):
  def say_son_hello(self):
     print("test  hello")

class HeroDaughter(Hero):
  def say_daughter_hello(self):
     print("test  hello daughter")

testson = HeroSon()
testson.say_class_hello()
testson.say_hello()
testdaughter = HeroDaughter()
testdaughter.say_class_hello()
testdaughter.say_hello()

The result is

"""
Hi Kido
Helllo...
Hi Princess
Helllo...
"""

We inherent Class Hero and as a base class, and we can implement method depends on the input type in base class.
In the method of say_class_hello can identify which subclass calling and execute different function programing by ourself.

More About This Example

Furthermore Adding the following line to the beginning of the cst_tuto.py.

print 'haha'
class tt(object):

    def __init__(self):
        print 'into init'
        self.a = 10

    @staticmethod
    def stamethod():
    .
    .
    .

Execute ii_tuto.py again

root@ubuntu:~/lab/python/classmethod# python ii_tuto.py
haha
in static
in klassmethod

You will see the result, when import cst the claim outside the class will be execute. Be careful about that, it will affect the performace alot, so clean it.

No comments:

Post a Comment