Python之面向对象
1.面向过程编程VS面向对象编程
面向过程编程(Procedural Programming):就是程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题 。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。
优点:将复杂的问题一步步分解,简化问题的复杂度
应用场景:面向过程的程序设计思想一般用于那些功能一旦实现之后就很少需要改变的场景, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的,著名的例子有Linux內核,git,以及Apache HTTP Server等。但如果你要处理的任务是复杂的,且需要不断迭代和维护 的, 那还是用面向对象最方便了。
面向对象编程(Object Oriented Programing):面向对象编程(OOP)编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述。
优点:1.使程序更加容易扩展和易更改,使开发效率变的更高。
2.基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
应用场景:当然是应用于需求经常变化的软件中,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
2.面向对象
2.1名词解释
- 类:一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型、模板。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
- 属性:人类包含很多特征,把这些特征用程序来描述的话,叫做属性,比如年龄、身高、性别、姓名等都叫做属性,一个类中,可以有多个属性
- 方法:人类不止有身高、年龄、性别这些属性,还能做好多事情,比如说话、走路、吃饭等,相比较于属性是名词,说话、走路是动词,这些动词用程序来描述就叫做方法。
- 实例(对象):一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
- 实例化:把一个类转变为一个对象的过程就叫实例化
2.2类与对象
2.2.1类与类的操作
定义类(类的命名、属性、方法)
class FactoryStaff: # 定义类,类名首字母大写 factory = '富士康' # 类的属性 def move(self): # 类的方法 print('搬运中...') print('搬运结束') def rest(self): print('休息中...') print('休息结束')
操作类
# 类的增操作 FactoryStaff.industry = '制造业' print(FactoryStaff.__dict__)
# 类的删操作 del FactoryStaff.industry print(FactoryStaff.__dict__)
# 类的改操作 FactoryStaff.industry = '手工业' print(FactoryStaff.__dict__)
注意:
- 类中可以有任意python代码,这些代码在类定义阶段便会执行,因而会产生新的名称空间,用来存放类的变量名与函数名,可以通过FactoryStaff.__dict__来查看
- 类中定义的名字,都是类的属性,点是访问属性的语法。
- 对于经典类来说我们可以通过该字典操作类名称空间的名字,但新式类有限制
2.2.2对象与对象的操作
创建(实例化)对象
# 实例化对象 Staff1 = FactoryStaff() # Staff1是类的实例,此过程是实例化 print(Staff1)
为对象添加独有属性
class FactoryStaff: # 定义类,类名首字母大写 factory = '富士康' # 类的属性 def __init__(self, name, sex, age): # 定义每个对象独有的属性 self.Name = name self.Sex = sex self.Age = age def move(self): # 类的方法 print('搬运中...') print('搬运结束') def rest(self): print('休息中...') print('休息结束') Staff1 = FactoryStaff('张三丰', '男', 50) print(Staff1.__dict__)
在定义类中添加了__init__()方法,运行结果如下:
对象操作
# 对象的增操作 Staff1.hobby = '太极' print(Staff1.__dict__)
# 对象的删操作 del Staff1.hobby print(Staff1.__dict__)
# 对象的改操作 Staff1.hobby = '足球' print(Staff1.__dict__)
注意:
- 站的角度不同,定义出的类是截然不同的;
- 现实中的类并不完全等于程序中的类,比如现实中的公司类,在程序中有时需要拆分成部门类,业务类等;
- 有时为了编程需求,程序中也可能会定义现实中不存在的类,比如策略类,现实中并不存在,但是在程序中却是一个很常见的类。
2.3属性查找与绑定方法
2.3.1属性查找
类有两种属性:数据属性和函数属性
1、类的数据属性是所有对象共享的
#类的数据属性是所有对象共享的,id都一样 print(id(FactoryStaff.factory)) # print(id(Staff1.factory)) # print(id(Staff2.factory)) # print(id(Staff3.factory)) #
2、类的函数数据是绑定给对象用的,称为绑定到对象的方法
#类的函数属性是绑定给对象使用的,obj.method称为绑定方法,内存地址都不一样 print(FactoryStaff.move) #<function FactoryStaff.move at 0x1021329d8> print(Staff1.move) #<bound method FactoryStaff.move of <__main__.FactoryStaff object at 0x1021466d8>> print(Staff2.move) #<bound method FactoryStaff.move of <__main__.FactoryStaff object at 0x102146710>> print(Staff3.move) #<bound method FactoryStaff.move of <__main__.FactoryStaff object at 0x102146748>> #id是python的实现机制,并不能真实反映内存地址,如果有内存地址,还是以内存地址为准
在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常
2.3.2绑定方法
首先,定义类并实例出三个对象
class FactoryStaff: # 定义类,类名首字母大写 factory = '富士康' # 类的属性 def __init__(self, name, sex, age): # 定义每个对象独有的属性 self.Name = name self.Sex = sex self.Age = age def move(self): # 类的方法 print('%s正在搬运中...' % self.Name) print('搬运结束') def rest(self): print('%s休息中...' % self.Name) print('休息结束') Staff1 = FactoryStaff('张一丰', '男', 50) Staff2 = FactoryStaff('张二丰', '男', 40) Staff3 = FactoryStaff('张三丰', '男', 30)
类中定义的函数(没有被任何装饰器装饰的),其实主要是给对象使用的,而且是绑定到对象的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法
强调:绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即自动传值(方法__init__也是一样的道理)如下:
Staff1.move() # 等价于FactoryStaff.move(Staff1) Staff2.rest() # 等价于FactoryStaff.rest(Staff2) FactoryStaff.move(Staff3) # 验证一下
运行结果:
注意:绑定到对象的方法的这种自动传值的特征,决定了在类中定义的函数都要默认写一个参数self,self可以是任意名字,但是约定俗成地写出self。