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