前言: oop很是很是很是重要。搞不懂oop,就玩不了python,就算能写也必定是写代码时候喜欢靠猜瞎猫碰死老鼠写得心很虚。为何这么说呢,我也是从面向过程编程到死走过来的,一路def到死,一看到有class的代码就逃到十万八千里了不想看,想千方设百计绕过这样的代码。不只不肯意看这样的代码,并且写代码时候很没思路,总是有一个想找一个本来有的相似的项目或模块,而后全盘复制过来,在里面进行扣字修改这种冲动。彻底从0开始亲手写一个稍微复杂的文件是不存在的,作不到这一点(不知道有没有人相同的感觉)。并且会下载不少pdf教程来学习阅读,但发现每一个教程关于面向对象总会有两三章的内容,每当看到这些章节教程来了就迅速结束阅读了,以为教程上总是花那么多章节介绍面向对象干鸟,我不用面向对象难道不行吗? 直到认真看了一个同事的代码和认真看了设计模式和面向对象后,基本上彻底无此困惑,基本上作到了从不复制,可以从容的从0开始写一个新的py文件,看py教程时候不只再也不很是恐惧面向对象的章节还特地很是喜欢看这些章节,基本上基础章节都是跳过专门看教程里面的面向对象章节。这就是学习oop和设计模式带给我最大的帮助,十分收益。10个python有9个不会oop8个从不用oop,这是我从公司人员写代码得出的规律,即便是月薪2万以上的人也是面向过程编程到死。通过对面向过程编程的代码进程改造,得出的规律是我能轻易使公司的任何模块和项目的代码减小40%-90%。同时咱们项目也有不少不断增长的功能和任务,别人一如既往面向过程编程到死,相同的任务,我老是能使用别人五分之一到二分之一的代码完成别人的全功能,由于代码少,因此在单位时间能作更多的平台。这些就是oop为何重要的缘由。那么此篇就是介绍,如何轻易使用oop,而不是死记硬背 封装 继承 多态 抽象这几个术语,由于背诵这几个术语对怎么转oop没有太大帮助,只有真正理解后才知道这些术语的含义。html
为何总是不会oop,总是容易陷入面向过程编程到死的窘境?学习oop的难点是 oop不是一种语法,他是一种思惟,语法很容易在10分钟内学会和背诵。思想是抽象的不像语法是具体的,因此这种思惟很难学,有的py人员一生都不会甚至不打算了解它。java
按照四步走的固定公式,能写模块就能抽象封装出一个好用的类。针对只会面向过程编程到死的python人员,按照此公式,能写模块就能写类,能写项目就能写框架。python
网上讲oop概念的不少,但没抽象出固定公式步骤,看了那些对转oo不能起到很大指导做用。据说py简单,就学py,但py害人就是很松散不是强制oop形成不思进取从不用oop写法不好,py能够平铺指令,也能够抽函数,也能够写面向对象。但大部分是前两种,只会前两种写法,对写生产项目坏处很大,致使写新模块和功能须要复制粘贴扣字,重复代码不少和调用麻烦和改一次逻辑须要改几百个地方和很差维护,有这些毛病。oop能使单个模块代码行数减小40% - 60%,oop加设计模式能使多个相似模块的代码行数减小最高达90%行代码。重要是不须要复制粘贴扣字几百次,新功能10行能代替让来150行,修改一处时候不须要学然来修改几百次容易改漏改错,心情很烦躁。以上这些减小的行数比例是我修改纯面向过程编程项目的不少个模块文件后得出的结论。c++
函数不是也能复用吗,只有类才能复用吗,写类是否是脱了裤子放屁?根据个人经验是若是问这两个的区别,那应该是对基本概念都严重牛头不对马嘴的产生混淆了。函数和类没有可比性,函数和类里面的方法才有得比。函数复用在不须要依赖外部变量和不须要外部函数(须要动态替换的外部依赖函数)和不须要在一组函数中反复传参和return结果的时候,才能比较好的效果,若是要修改一个函数所依赖的外部函数不方便,尤为是依赖外部全局变量但又有须要多实例方面的需求困惑,纯函数更是难以搞定,能写但必然写得很曲折。不是全部东西必定要oop,因此能够根据这条来判断是否要修改为oop,而不是笼统的听网上说简单的用函数复杂的用类,这没有判断依听说什么才叫简单和复杂。同理若是不须要用类的但强行写类反而是没有理解透彻面向对象能比原来的写法带来什么好处,无论三七二十一什么都写类我是持反对态度的。面向过程的函数的复用是输入输出转换级别的复用做用是y = f(x),面向对象的类的复用是框架级别复用、流程级别的复用,函数是和方法来比,函数和类比是牛头不对马嘴的比较,函数的复用和面向对象级别的复用差远了。编程
一般老师在讲面向对象时候,会讲类和对象的关系,而后接着就是开始定义一个类了,老师会在类里面演示定义几个属性。但为何要在类里面定义几个属性(或者叫成员变量)呢,定义他干什么?有什么好处?全部类都不要属性能够吗,不要属性好很差?在面向过程编程时候没有属性或者成员变量是怎么绕开解决这个成员变量的? 通常都没讲这几个缘由,致使学生不知道为何要oop和oop比opp好在哪里能解决什么事情。设计模式
除了这个通用公式,那么提升oo和代码水平的方法是看w3school或者菜鸟教程的设计模式教程。每月至少看一次36种设计模式,每月都要看一次。每一种模式都是oop封装的浓缩精华案例。框架
一、以前写的这个好久了 编辑器
里面提到的是三步走:函数
模块和类的转换规则是:工具
一、模块级降为类
二、全局变量改为实例属性,全局的不会被改变的变量相似于那种const的,能够写成类属性(减小点内存存储能够)。何时须要类属性何时须要实例属性,酌情考虑。
三、而后把函数改为方法。方法是类里面的,函数是模块里面的。
由于里面举得一个例子是一我的,但人的属性写的是模块级全局变量,若是是这种写法,三步走就能够oo了。
二、但如今的状况是不少人不喜欢写全局变量(不写全局是为了尽量模拟多实例,这就不可能用全局变量了,由于全局变量在整个python模块的命名空间下只有一份;并且是但愿从入口函数传不一样的参获得不一样的运行结果,不但愿是经过修改顶层代码的全局变量来获得不一样的运行结果,因此才会出现尽可能少写全局变量这种现象了),喜欢一步一步一环套一环的传参和return来处理业务,那么这种写法,若是仅仅按照上面的三步走战略,就不够了,由于只执行这三步后 ,只是有了class外壳,但丝毫没有封装的概念,这样作是没有个卵用的。我最近就看过一些这样的类,写的貌合神离,貌像面向对象,但神是面向过程,这种类固然是十分的不必,这种写法除了在长篇幅的模块文件中割裂出更小命名空间,使各部分功能紧凑一点之外,由于没有体现出面向对象带来的任何优势,也没任何意义了,直接在这种写法方式的面向过程的代码的基础上,执行这三步加个class关键字,只不过是脱了裤子放屁。
若是是这种思惟来写的面向过程,那么三步走还不行,须要从新构思整个流程,即在代码里面少return少传参,多用全局变量,按照这个思路在脑壳里面过一遍,这一步是发生在脑壳里面的,不是让你真在代码写全局变量,是为了先构思出来有哪些传参和return能够弄成全局变量,而后再接着上面的三步走战略,降级命名空间,就是oo了。
因此这个前置的发生在脑壳里面的过程是不能少的,这一步是整个精神支柱 ,后面三步是修改代码面貌,脑壳里面不先打好这一步的草稿就匆忙的执行三步走战略,写出这种类来,在一些有五六年开发经验的老手看来,会以为写这个python类是在强行装逼,代码有点滑稽。有人问是否是代码里面多写class关键字就是面向对象了?大错特错,面向对象oop和代码有没有class没有必然关系,他是一种思惟思想不是语法形式,举例一个使用你们公认的强制面向对象的语言java语言来用面向过程的思惟写代码的例子,若是也按这种写法写python的类,这种就是属于无效装逼类。
下面例子使用java,例举了两种写法,一种是使用面向过程,一种是使用面向对象来写,不用说,代码确定有class关键字,java没class不行。
三、那么总结一下就是四步走了:
0)、若是你的代码已是按照个人那我的 的那个类那种全局变量加函数的写法能够跳过这一步。若是是第2种状况彻底一环套一环的在每一个函数节点里面return加传参的写法,那么先须要执行下面这段话。
在你的脑瓜里面构思,你的面向过程的return 传参,有哪些尽量多的是能够弄成全局变量的,这时候不用考虑全局变量是否是须要多份的,由于后面在三步走命名空间降级的时候,这个玩意自动变成了实例属性,而每一个类的多个实例的的属性都是互不干扰的,除非了你刻意写了单例模式。
1)、模块级降为类
2)、全局变量改为实例属性,全局的不会被改变的变量相似于那种const的,能够写成类属性(减小点内存存储能够)。何时须要类属性何时须要实例属性,酌情考虑。
3)、而后把函数改为方法。方法是类里面的,函数是模块里面的。
第0步发生在脑壳里面,后面三步发生在代码编辑器里面。跳过第0步直接进行后面三步,那就会写出面向过程的废物装x滑稽类。
面向对象本质是方法和属性的封装,若是不容许写任何一个实例属性,把全部属性绑定所有改成外界传参给方法,全部原来保存中间状态的实例属性所有return给外界保存,那写这样的类,基本上是没个鸟用,废了面向对象的80%功能优势,只不过是加个class外壳罢了。
为何是废了面向对象80%优势,面向对象除了封装不是还有继承和多态吗?若是没有任何实例属性 ,那么全部方法就没有须要访问实例属性了,全部方法应该声明为静态方法,对一组纯静态方法的类玩继承和多态基本上没有太多意义,若是能理解这个,就能够想到 随便查看了100万个 正确运行的java代码,能够得出一个规律:一个方法的前缀永远不可能同时出现abstract 和 static两个关键字,这两个是关键字是互斥的。静态方法由类名调用,该方法也不访问任何实例属性,也就是是静态方法与对象自己无关,多态时候静态方法只会使用父类的方法,不使用子类的方法,在一组纯静态方法的工具类的基础上玩继承多态基本上是无卵意义,由于没有卵的必要性,因此直接在语法层面上禁止这两个关键字同时出现,不然会报错。
四、面向过程人员调用一个类,应该怎么想?
若是仍是彻底不熟悉类,对模块加函数更熟悉,那屡次实例化一个类到底用熟悉的思惟怎么想象他?上面的是说怎么写类,是模块降级为类了。调用类时候,思惟也能够升级,从新把类在脑瓜里面升级为模块级写法,把实例化构造函数传参想象为修改全局变量,调用方法想象为调用函数。
类能够实例化无数次,彻底能够把实例化出来的对象想象为无数个状态属性互不干扰的复制的模块。 因此回到3,就是为何要写类而不是写模块加全局变量加函数了,模块是单例,不一样的地方使用模块使用的是模块的相同的全局变量,小红用了这个模块后,修改了全局变量,小明再调用,究竟是不是要重置全局变量状态,不改,小明是女的了,改了小明成男的,但若是其余函数调用了性别全局变量,小红再调用尿尿函数,小红就变成男的告终果成了站着尿尿不是蹲着尿尿,由于这就很牟盾,因此要进行降维。类是多实例,模块是单实例。
五、虽然网上都说面向过程转面向对象很难,要靠领悟和实践,没有捷径可走。但完成基本的面向对象转变,能够按照这个公式,严格执行四步走战略。其他的就是多实践多对比领悟摸索,想玩的精妙须要学习23种设计模式。
六、说完怎么转oo的公式了,还必须交代为何这么作呢。
有不少人就信口雌黄坚决并坚持地说python面向对象是废物没鸟用,python里面写class彻底没有一丝必要,说java要写类那是java语法规定死了必需要写class,认为python在类里面写方法和直接在模块下面写函数效果彻底100%等同,这么个说法是由于只是由于他长期只使用面向过程没有自定义过一次类,作事只顾完成一个功能,不讲究任何维护和扩展,胡说八道了,能够写函数不是必定要全写函数,那用c++时候若是无论是什么项目什么场景坚持全写函数,那要c++这种语言存在干什么,用c就行了。以前举了不少例子说明oo和op对比的优势,大道理就不用讲,直接用一个反证法就能轻易反驳这种说法了,光去看看三方包,有哪一个包是纯面向过程的?若是真的纯面向过程,那个包调用起来确定很是的苦逼。若是没用,那发明python的人是吃饱了撑着闲的蛋疼加个类进去,他们为何不移除面向对象?这么瞎说的人难道是以为本身已经彻底超越了发明python语言的人和全部开发三方库的人的认知水平了吗?