美文网首页Python常用
@classmethod和@staticmethod的区别

@classmethod和@staticmethod的区别

作者: Alex_Dj | 来源:发表于2018-02-03 12:02 被阅读0次

    简介

    类的成员

    python中类的成员可以分为三大类:字段、方法和属性


    类的方法

    包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同

    • 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
    • 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
    • 静态方法:由类调用;无默认参数;

    三者相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份
    三者不同点:方法调用者不同、调用方法时自动传入的参数不同

    普通方法是最常见的方法,大家都比较熟悉。本文要讨论的是类方法和静态方法


    定义和调用

    定义
    class Foo():
        def __init__(self, name):
            self.name = name
        
        def bar(self):
            """
            定义普通方法:至少需要一个参数self
            """
            print('Hello,{}'.format(self.name))
    
        @classmethod
        def class_foo(cls, x):
            """
            定义类方法:至少需要一个cls参数
            """
            print('Executing class_foo({}, {})'.format(cls, x))
    
        @staticmethod
        def static_foo(x):
            """
            定义静态方法:无默认参数
            """
            print('Executing static_foo({})'.format(x))
    

    在定义上静态方法staticmethod和类方法classmethod需要分别使用装饰器@staticmethod、@classmethod

    调用

    普通方法在调用之前需要先对类进行实例化。调用方法:实例名.方法名()

    In [2]: foo = Foo('bar')
    
    In [3]: foo.bar()
    Hello,bar
    

    类方法可直接使用类名.方法名()调用。调用方法:类名.方法名()或者实例名.方法名()

    In [4]: foo.class_foo(1)
    Executing class_foo(<class '__main__.Foo'>, 1)
    
    In [5]: Foo.class_foo(1)
    Executing class_foo(<class '__main__.Foo'>, 1)
    

    静态方法的也可直接使用类名.方法名()调用。调用方法:类名.方法名()或者实例名.方法名()

    In [6]: foo.static_foo(1)
    Executing static_foo(1)
    
    In [7]: Foo.static_foo(1)
    Executing static_foo(1)
    

    两者的不同

    @classmethod

    如果我们想创建一个在类中(而不是在实例中)运行的方法,我们可以这样做:

    def iget_no_of_instance(ins_obj):
        return ins_obj.__class__.no_inst
     
    class Kls(object):
        no_inst = 0
     
        def __init__(self):
        Kls.no_inst = Kls.no_inst + 1
     
    ik1 = Kls()
    ik2 = Kls()
    print iget_no_of_instance(ik1)
    

    在Python2.2以后可以使用@classmethod装饰器来创建类方法.

    class Kls(object):
        no_inst = 0
     
        def __init__(self):
            Kls.no_inst = Kls.no_inst + 1
     
        @classmethod
        def get_no_of_instance(cls_obj):
            return cls_obj.no_inst
     
    ik1 = Kls()
    ik2 = Kls()
     
    print ik1.get_no_of_instance()
    print Kls.get_no_of_instance()
    

    使用@classmethod的好处是:无论我们是从类中还是从实例中调用方法,都会将传给第一个参数。

    @staticmethod

    我们经常需要用到一些和类有关的功能,但又无需类或实例参与——例如如设置环境变量,改变另外一个类的属性等。在这些情况下,我们也可以直接使用函数,但这样做的话会将相关的代码块分开,导致后期的维护问题。
    简单的例子如下:

    def checkind():
        return (IND == 'ON')
     
    class Kls(object):
         def __init__(self,data):
            self.data = data
     
        def do_reset(self):
            if checkind():
                print('Reset done for:', self.data)
         
        def set_db(self):
            if checkind():
                self.db = 'new db connection'
                print('DB connection made for:',self.data)
    

    得到的输出:

    Reset done for: 12
    DB connection made for: 12
    

    如果我们使用@staticmethod,我们可以将所有代码放在同一个代码块里:

    IND = 'ON'
     
    class Kls(object):
        def __init__(self, data):
            self.data = data
     
        @staticmethod
        def checkind():
            return (IND == 'ON')
     
        def do_reset(self):
            if self.checkind():
                print('Reset done for:', self.data)
     
        def set_db(self):
            if self.checkind():
                self.db = 'New db connection'
            print('DB connection made for: ', self.data)
     
    ik1 = Kls(12)
    ik1.do_reset()
    ik1.set_db()
    

    输出:

    Reset done for: 12
    DB connection made for: 12
    



    参考
    1. Difference between @staticmethod and @classmethod in Python
    2. What is the difference between @staticmethod and @classmethod in Python?
    3. python 面向对象(进阶篇)

    相关文章

      网友评论

        本文标题:@classmethod和@staticmethod的区别

        本文链接:https://www.haomeiwen.com/subject/pyayzxtx.html