zoukankan      html  css  js  c++  java
  • python中 staticmethod与classmethod

    原文地址https://blog.csdn.net/youngbit007/article/details/68957848

    原文地址https://blog.csdn.net/weixin_35653315/article/details/78165645

    原文地址https://www.cnblogs.com/1204guo/p/7832167.html

    在Python里, 在class里定义的方法可以大致分为三类: 实例方法, 类方法与静态方法.

    用一个表格总结如下:

    方法类型修饰调用者默认首参
    实例方法 instance self
    类方法 @classmethod cls, instance cls
    静态方法 @staticmethod cls, instance

    示例:

    class Foo():
        # 无修饰
        def instance_method(self): #传入的第一个参数是self, 即instance本身
            print('the first argument of instance_method:', self)
    
        @classmethod
        def class_method(cls): # 传入的第一个参数是class
            print('the first argument of class_method:', cls)
    
        @staticmethod
        def static_method(): # 没有默认的首位参数, 只有自定义参数
            print('the first argument of static_method:')
    
    foo = Foo()
    foo.instance_method()
    Foo.class_method()
    foo.class_method()
    Foo.static_method()
    foo.static_method()
    try:
        Foo.instance_method()
    except:
        print('instance method can not be accessed through class.')

    输出:

    the first argument of instance_method: <__main__.Foo object at 0x7fd135ec3b38>
    the first argument of class_method: <class '__main__.Foo'>
    the first argument of class_method: <class '__main__.Foo'>
    the first argument of static_method:
    the first argument of static_method:
    instance method can not be accessed through class

    需要注意: 
    1. @classmethod@staticmethod是Python的built-in methods. 
    2. 特殊方法__new__虽然不用@classmethod修饰, 但它也是class method.

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------

    classmethod:类方法 
    staticmethod:静态方法

    在Python中,静态方法和类方法都是可以通过类对象和类对象实例访问。但是区别是:

    @classmethod 是一个函数修饰符,它表示接下来的是一个类方法,而对于平常我们见到的则叫做实例方法。 类方法的第一个参数cls,而实例方法的第一个参数是self,表示该类的一个实例。

    普通对象方法至少需要一个self参数,代表类对象实例

    类方法有类变量cls传入,从而可以用cls做一些相关的处理。并且有子类继承时,调用该类方法时,传入的类变量cls是子类,而非父类。

    对于类方法,可以通过类来调用,就像C.f(),有点类似C++中的静态方法, 也可以通过类的一个实例来调用,就像C().f(),这里C(),写成这样之后它就是类的一个实例了。

    静态方法则没有,它基本上跟一个全局函数相同,一般来说用的很少

    classmethod必须使用类对象作为第一个参数,而staticmethod则可以不传递任何参数。

    class Date:
    
        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('-'))
            my_date = cls(day, month, year)
            return my_date
    
        @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
    
    
    if __name__ == '__main__':
        my_date = Date.from_string('11-09-2012')
        print(my_date.day, my_date.month,my_date.year)
        is_date = Date.is_date_valid('13-13-2012')
        print(is_date)
    
    outputs: 
    11 9 2012
    False

    在来看另外的例子,为了验证有子类继承时,子类调用该类方法时,传入的类变量cls是子类,而非父类

    class A:
        @classmethod
        def cm(cls):
            print('类方法cm(cls)调用者:', cls.__name__)
    
        @staticmethod
        def sm():
            print('静态方法sm()被调用')
    
    class B(A):
        pass
    
    A.cm()  # 类方法cm(cls)调用者: A
    B.cm()  # 类方法cm(cls)调用者: B
    A.sm()  # 静态方法sm()被调用
    B.sm()  # 静态方法sm()被调用

    下面我们来看为什么要用到staticmethod与classmethod。

    class Kls:
        def __init__(self,data):
            self.data = data
        def printd(self):
            print(self.data)
    
    ik1=Kls('arun')
    ik2=Kls('seema')
    ik1.printd()
    ik2.printd()
    # 如果现在我们想写一些仅仅与类交互而不是和实例交互的方法会怎么样呢? 我们可以在类外面写一个简单的方法来做这些,
    # 但是这样做就扩散了类代码的关系到类定义的外面. 如果像下面这样写就会导致以后代码维护的困难:
    def get_no_of_instances(cls_obj):
        return cls_obj.no_inst
    class Kls:
        no_inst = 0
        def __init__(self):
            Kls.no_inst = Kls.no_inst + 1
    ik1 = Kls()
    ik2 = Kls()
    print(get_no_of_instances(Kls)) # 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())
    # 2
    # 2

    @staticmethod 
    经常有一些跟类有关系的功能但在运行时又不需要实例和类参与的情况下需要用到静态方法

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Python的方法主要有3个,即静态方法(staticmethod),类方法(classmethod)和实例方法,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def foo(x):
        print "executing foo(%s)"%(x)
      
    class A(object):
        def foo(self,x):
            print "executing foo(%s,%s)"%(self,x)
      
        @classmethod
        def class_foo(cls,x):
            print "executing class_foo(%s,%s)"%(cls,x)
      
        @staticmethod
        def static_foo(x):
            print "executing static_foo(%s)"%x
      
    a=A()

    这个self和cls是对类或者实例的绑定,对于一般的函数来说我们可以这么调用foo(x),这个函数就是最常用的,它的工作跟任何东西(类,实例)无关.对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是foo(self, x),为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的a.foo(x)(其实是foo(a, x)).类方法一样,只不过它传递的是类而不是实例,A.class_foo(x).注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好.

    对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用a.static_foo(x)或者A.static_foo(x)来调用.

  • 相关阅读:
    Linux CAT与ECHO命令详解
    查看linux版本信息
    kubernetes(一)
    Chrome不安装插件实现页面长截图
    centos 升级glibc-2.17
    redis修改大key报Argument list too long的解决办法
    mysql打印用户权限的小技巧
    Centos6.5 自带的Python2.6.6 如何安装setuptools和pip
    TCP三次握手过程中涉及的队列知识的学习
    Docker volume权限导致的几个问题
  • 原文地址:https://www.cnblogs.com/111testing/p/9613227.html
Copyright © 2011-2022 走看看