美文网首页
Python @classmethod

Python @classmethod

作者: Robots小助手 | 来源:发表于2020-02-01 10:41 被阅读0次

    以下内容来自万能的互联网...

    碎碎念:这些文章都是记录我学习Python过程中,教程里面写的简单,脑子笨,自己上网搜的,把这些东东拼凑在一起。。。

    首先教材上的

    1.@classmethod必须位于方法上面一行
    2.第一个cls必须有,cls指的就是“类对象”本身
    3.调用类方法:类名.类方法名(参数列表)。参数列表中不需要也不能给cls传值。
    4.类方法中访问实例属性和实例方法会导致错误
    5.子类继承父类方法时,传入cls的是子类对象,而非父类对象

    1.什么是classmethod

    classmethod是用来指定一个类的方法为类方法,长的像下面这个样子

    class cc:
        @classmethod
        def f(cls, arg1, arg2, ...): ...
    

    cls通常用作类方法的第一参数 跟self有点类似( init里面的slef通常用作实例方法的第一参数)。即通常用self来传递当前类对象的实例,cls传递当前类对象。self 和cls 没有特别的含义,作用只是把参数绑定到普通的函数上, 不一定非得是slef 或cls , 可以换成别的xxx.

    2.为啥会有classmethod

    1--classmethod设计的目的是什么呢?

    事实上与Python面向对象编程有关的,由于Python不支持多个的參数重载构造函数,比方在C++里,构造函数能够依据參数个数不一样。能够写多个构造函数。Python为了解决问题,採用classmethod修饰符的方式,这样定义出来的函数就能够在类对象实例化之前调用这些函数,就相当于多个构造函数,解决多个构造函数的代码写在类外面的问题。

    2--实例化对象前交互

    类最基本的作用是实例化出一个对象,但是有的时候再实例化之前,就需要先和类做一定的交互,这种交互可能会影响实际实例化的过程,所以必须放在调用构造函数之前。

    3--方便不通过实例化直接调用

    直接一点来说,我们知道对于一个普通的类,我们要使用其中的函数的话,需要对类进行实例化,而一个类中,某个函数前面加上了staticmethod或者classmethod的话,那么这个函数就可以不通过实例化直接调用,可以通过类名进行调用的

    4--保证继承后的实例是子类的实例

    @classmethod 定义的类方法是可选构造函数中,我们定义了一个类方法,类方法的第一个参数(cls)指代的就是类本身。类方法会用这个类来创建并返回最终的实例。使用类方法的另一个好处就是在继承的时候,保证了子类使用可选构造函数构造出来的类是子类的实例而不是父类的实例。

    3.classmethod有什么用

    在Java等语言中,这类功能通常通过工厂类(Factory)实现,先初始化一个工厂类的实例,然后由这个工厂类的实例构造实际需要的实例。在Python中,普通类完全可以替代Factory,而对于支持配置的Factory,就对应到相应的classmethod。
    Python中的classmethod(和staticmethod)并不止拥有美学上(或者命名空间上)的意义,而是可以实际参与多态的、足够纯粹的OOP功能,原理在于Python中类可以作为first class的对象使用,很大程度上替代其他OOP语言中的工厂模式。classmethod既可以作为factory method提供额外的构造实例的手段,也可以作为工厂类的接口,用来读取或者修改工厂类本身。classmethod还可以通过额外的类引用,提供继承时的多态特性,实现子类挂载点等。

    class Data_test(object):
        day=0
        month=0
        year=0
        def __init__(self,year=0,month=0,day=0):
            self.day=day
            self.month=month
            self.year=year
     
        def out_date(self):
            print "year :"
            print self.year
            print "month :"
            print self.month
            print "day :"
            print self.day
    t=Data_test(2016,8,1)
    t.out_date()
    

    输出:
    year :
    2016
    month :
    8
    day :
    1
    符合期望。


    如果用户输入的是 "2016-8-1" 这样的字符格式,那么就需要调用Date_test 类前做一下处理:
    string_date='2016-8-1'
    year,month,day=map(int,string_date.split('-'))
    s=Data_test(year,month,day)

    先把‘2016-8-1’ 分解成 year,month,day 三个变量,然后转成int,再调用Date_test(year,month,day)函数。 也很符合期望。那我可不可以把这个字符串处理的函数放到 Date_test 类当中呢?
    那么@classmethod 就开始出场了

    class Data_test2(object):
        day=0
        month=0
        year=0
        def __init__(self,year=0,month=0,day=0):
            self.day=day
            self.month=month
            self.year=year
     
        @classmethod
        def get_date(cls,data_as_string):
            #这里第一个参数是cls, 表示调用当前的类名
            year,month,day=map(int,string_date.split('-'))
            date1=cls(year,month,day)
            #返回的是一个初始化后的类
            return date1
     
        def out_date(self):
            print "year :"
            print self.year
            print "month :"
            print self.month
            print "day :"
            print self.day
    

    在Date_test类里面创建一个成员函数, 前面用了@classmethod装饰。 它的作用就是有点像静态类,比静态类不一样的就是它可以传进来一个当前类作为第一个参数。

    那么如何调用呢?

    r=Data_test2.get_date("2016-8-6")
    r.out_date()
    输出:
    year :
    2016
    month :
    8
    day :
    1


    这样子等于先调用get_date()对字符串进行出来,然后才使用Data_test的构造函数初始化。这样的好处就是你以后重构类的时候不必要修改构造函数,只需要额外添加你要处理的函数,然后使用装饰符 @classmethod 就可以了。

    相关文章

      网友评论

          本文标题:Python @classmethod

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