介绍模块和类怎么互相转换,不谈面向对象的继承 封装 多态等特色。php
一个person_module模块,有人的基本属性和功能。html
person_module.py以下java
# coding=utf8 name = '小明' eye_color = 'blue' age = 10 def get_eye_color(): return name + '的眼睛颜色是: ' + eye_color def show_age(): print name + '的年龄是: ' + str(age) def grow(): print name + ' 增加一岁了' globals()['age'] += 1 ##这里要注意必定要这样写活着声明age是全局的,不然会出错 print globals()['age'] show_age() if __name__ == "__main__": print get_eye_color() show_age() grow()
如今假如这个模块是别人写的,咱们拿来用,如今咱们要把名字换成小红,眼睛颜色换成黑色,年龄换成15岁,成长函数,一次增长两岁python
那咱们就须要修改别人的源码文件了,可能改着改着改错了,不知道怎么复原了。es6
那就import这个模块吧。web
xiaohong.py编程
# coding=utf8 import person_module as p from person_module import * p.name = '小红' p.age = 14 p.eye_color = 'black' def grow(): print p.name + ' 增加一岁了' p.age += 2 print p.age show_age() p.grow = grow print p.get_eye_color() show_age() p.grow() # 直接grow()也能够
能够看到属性被替换了,连增加函数也被替换了,一次增加两岁。设计模式
这就是给模块打猴子补丁了,这样写很别扭的实现了模块继承,相似于类继承。函数
但愿把这个模块转换成类,oop编程。工具
模块和类的转换规则是:
一、模块级降为类
二、全局变量改为实例属性,全局的不会被改变的变量相似于那种const的,能够写成类属性(减小点内存存储能够)。
三、而后把函数改为方法。方法是类里面的,函数是模块里面的。
看person.py
# coding=utf8 class Person(object): def __init__(self, name, age,eye_color): self.name = name self.eye_color = eye_color self.age = age def get_eye_color(self): return self.name + '的眼睛颜色是: ' + self.eye_color def show_age(self): print self.name + '的年龄是: ' + str(self.age) def grow(self): print self.name + ' 增加一岁了' self.age += 1 self.show_age() if __name__ == "__main__": xiaohong = Person('小红', 14, 'black') print xiaohong.get_eye_color() xiaohong.show_age() xiaohong.grow()
这样作了以后,统一经过self就能访问age name了,改变age也不须要蛋疼的声明一下age是全局的那个了。
就这样三个步骤,就能把面向过程的模块改为面向对象了。
最主要是前面那种导入模块的方法,打补丁很麻烦,那例子还只是实现小红,若是要实现小黄、小花,那就复杂了。若是使用oop,类的多个实例就天然多了,也简单直观。
若是要改变grow方法,继承一下就好了,改为这样
大部分入门都是第一种写法,毕竟py编程太自由了,能够一条条从上往下指令平铺,也能够抽成函数,也能够oop。用py会长期造成了懒惰的写法用前面第一种,但复用性真的比oop差不少,整体看起来也low一些。好比多个过程须要共享中间状态时,单纯的使用函数会写得很糟糕,这时候就应当使用类,不然要么搞全局变量要么频繁的return频繁的传参,为何反对模块编程,就是由于模块难以初始化赋值,模块的多实例难以搞,类能很好解决。非oop一些设计模式很难用上。也有人坚定说他不须要oop,说不须要那是没认真对比过,或者压根不了解,只是死记硬背类的 继承 封装多态这几个词语,并无实践对比过。还有的说python里面一切皆是对象,因此他写的就是oop,没错,那样仅限于有int 类 str类 字典类 或者导入了三方库后有了Request类 Response类,selenim的webdriver的Chrome类 Firefox类,仅限于此啊,没有本身的类,python一切皆对象(在py里面随便写个 a = 5,a就能够说是int类的一个实例了,py是面向对象的极致,甚至比java还极致,java里面的int a = 5,a是基本数据类型,要用到一些必要的方法支持还的把a转成Interger类的对象,php里面的字符串操做是由函数完成的,php的小写字符串转大写是 strtoupper("Hello WORLD!"),py的小写转大写是“Hello WORLD!”.uper(),object.func()和func(object)就是op和oo的区别。除了py里面的例如__len__用,len(str1)来获取长度,但这种是经过反射完成,也能够用str.__len__(),len(str)形式上看起来不那么oo。)虽然py一切皆对象,py是最极致的面向对象,但这不表明随便写就是oop编程了。三方库为何调用的那么爽,那是人家oop了,人家三方库全写函数,调用起来就知道什么叫痛苦了,都不知道应该调用哪些函数来处理那个对象了。这都什么年代了,还对oop持怀疑和反对态度。php py js es6都是在慢慢的后来加入类的概念,难道发明语言的人会比咱们差吗。
必须对py的oop很是熟悉,才能开始学习java。否则的是确定看不懂java。
一个模块内能够多个类,类能够把模块分割裂更小的模块组织单元。oo大量实例化时候须要占用更多的内存,性能是比op差。若是担忧oo性能比op差,那同样能够适当地写类里面的静态方法或者类方法,无需实例化,经常使用的工具方法不要全写成实例方法,干个啥都要实例化,该用静态就要用静态。
这是一些体会,po和oo每次写时候顺便脑补一下,另外一种大概是怎么样的。全局变量太多,多个函数操做一个东西,就能够想下oop,oo能消灭全局,平铺式的代码适合简单脚本,或者快速验证和测试或者顶层脚本,但若是是做为被导入模块,再用这种写法,模块里面大量写非final类型的全局变量是很脑残的低级入门写法。模块级的po是拿个源码脚本,处处去修改一些变量的值,例如age name什么的。oo是对数据和方法的封装,op是函数和传参分离在两个地方。
以上为简单例子,oop的进阶是设计模式。
若是不是按照这种写人的方式,全局变量加函数的面向过程写法,而是彻底的没有全局变量一步步return和传参的,执行三步走那就是只有class外壳的类,仍然是一个面向过程的类,须要再加一步。