学习oop的难点是 oop不是一种语法,他是一种思维,语法很容易在10分钟内学会和背诵。思想是抽象的不像语法是具体的,所以这种思维很难学,有的py人员一辈子都不会甚至不打算了解它。
按照四步走的固定公式,能写模块就能抽象封装出一个好用的类。针对只会面向过程编程到死的python人员,按照此公式,能写模块就能写类,能写项目就能写框架。
网上讲oop概念的很多,但没抽象出固定公式步骤,看了那些对转oo不能起到很大指导作用。听说py简单,就学py,但py害人就是很松散不是强制oop造成不思进取从不用oop写法很差,py可以平铺指令,也可以抽函数,也可以写面向对象。但大部分是前两种,只会前两种写法,对写生产项目坏处很大,导致写新模块和功能需要复制粘贴扣字,重复代码很多和调用麻烦和改一次逻辑需要改几百个地方和不好维护,有这些毛病。oop能使单个模块代码行数减少40% - 60%,oop加设计模式能使多个类似模块的代码行数减少最高达90%行代码。重要是不需要复制粘贴扣字几百次,新功能10行能代替让来150行,修改一处时候不需要学然来修改几百次容易改漏改错,心情很烦躁。以上这些减少的行数比例是我修改纯面向过程编程项目的很多个模块文件后得出的结论。
函数不是也能复用吗,只有类才能复用吗,写类是不是脱了裤子放屁?根据我的经验是如果问这两个的区别,那应该是对基本概念混淆了。函数和类没有可比性,函数和类里面的方法才有得比。函数复用在不需要依赖外部变量和不需要外部函数(需要动态替换的外部依赖函数)和不需要在一组函数中反复传参和return结果的时候,才能比较好的效果,如果要修改一个函数所依赖的外部函数不方便,尤其是依赖外部全局变量但又有需要多实例方面的需求困惑,纯函数更是难以搞定,能写但必然写得很曲折。不是所有东西一定要oop,所以可以根据这条来判断是否要修改成oop,而不是笼统的听网上说简单的用函数复杂的用类,这没有判断依据说什么才叫简单和复杂。同理如果不需要用类的但强行写类反而是没有理解透彻面向对象能比原来的写法带来什么好处,不管三七二十一什么都写类我是持反对态度的。
除了这个通用公式,那么提高oo和代码水平的方法是看w3school或者菜鸟教程的设计模式教程。每个月至少看一次36种设计模式,每个月都要看一次。每一种模式都是oop封装的浓缩精华案例。
1、之前写的这个很久了
里面提到的是三步走:
模块和类的转换规则是:
1、模块级降为类
2、全局变量改成实例属性,全局的不会被改变的变量类似于那种const的,可以写成类属性(减少点内存存储可以)。什么时候需要类属性什么时候需要实例属性,酌情考虑。
3、然后把函数改成方法。方法是类里面的,函数是模块里面的。
因为里面举得一个例子是一个人,但人的属性写的是模块级全局变量,如果是这种写法,三步走就可以oo了。
2、但现在的情况是很多人不喜欢写全局变量(不写全局是为了尽可能模拟多实例,这就不可能用全局变量了,因为全局变量在整个python模块的命名空间下只有一份;而且是希望从入口函数传不同的参得到不同的运行结果,不希望是通过修改顶层代码的全局变量来得到不同的运行结果,所以才会出现尽量少写全局变量这种现象了),喜欢一步一步一环套一环的传参和return来处理业务,那么这种写法,如果仅仅按照上面的三步走战略,就不够了,因为只执行这三步后 ,只是有了class外壳,但丝毫没有封装的概念,这样做是没有个卵用的。我最近就看过一些这样的类,写的貌合神离,貌像面向对象,但神是面向过程,这种类当然是十分的没必要,这种写法除了在长篇幅的模块文件中割裂出更小命名空间,使各部分功能紧凑一点以外,因为没有体现出面向对象带来的任何优点,也没任何意义了,直接在这种写法方式的面向过程的代码的基础上,执行这三步加个class关键字,只不过是脱了裤子放屁。
如果是这种思维来写的面向过程,那么三步走还不行,需要重新构思整个流程,即在代码里面少return少传参,多用全局变量,按照这个思路在脑袋里面过一遍,这一步是发生在脑袋里面的,不是让你真在代码写全局变量,是为了先构思出来有哪些传参和return可以弄成全局变量,然后再接着上面的三步走战略,降级命名空间,就是oo了。
所以这个前置的发生在脑袋里面的过程是不能少的,这一步是整个精神支柱 ,后面三步是修改代码面貌,脑袋里面不先打好这一步的草稿就匆忙的执行三步走战略,写出这种类来,在一些有五六年开发经验的老手看来,会觉得写这个python类是在强行装逼,代码有点滑稽。
3、那么总结一下就是四步走了:
0)、如果你的代码已经是按照我的那个人 的那个类那种全局变量加函数的写法可以跳过这一步。如果是第2种情况完全一环套一环的在每个函数节点里面return加传参的写法,那么先需要执行下面这段话。
在你的脑瓜里面构思,你的面向过程的return 传参,有哪些尽可能多的是可以弄成全局变量的,这时候不用考虑全局变量是不是需要多份的,因为后面在三步走命名空间降级的时候,这个玩意自动变成了实例属性,而每个类的多个实例的的属性都是互不干扰的,除非了你刻意写了单例模式。
1)、模块级降为类
2)、全局变量改成实例属性,全局的不会被改变的变量类似于那种const的,可以写成类属性(减少点内存存储可以)。什么时候需要类属性什么时候需要实例属性,酌情考虑。
3)、然后把函数改成方法。方法是类里面的,函数是模块里面的。
第0步发生在脑袋里面,后面三步发生在代码编辑器里面。
面向对象本质是方法和属性的封装,如果不允许写任何一个实例属性,把所有属性绑定全部改为外界传参给方法,所有原来保存中间状态的实例属性全部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语言的人和所有开发三方库的人的认知水平了吗?