一 . 面向对象编程
1. 什么是面向对象:
面向过程程序设计:核心是过程二字, 过程指的是解决问题的步骤, 即先干什么在干什么. 面向过程的设计就好比精
心
设计好一条流水线, 是一种机械式的思维方式
优点 : 复杂度的问题流程化, 进而简单化(一个复杂的问题,分成一个个小的步骤去实现. 实现小的步骤将会非常简
单)
缺点 : 一套流水线或者流程就是用来解决一个问题, 生产汽水的流水线无法生产汽车, 即便是能, 也得是大改, 改
一个组件, 牵一发而动全身,
而面向对象的程序设计 :核心是对象二字,
(要理解对象为何物, 必须把自己当成上帝,上帝眼里的世间存在的万物)
皆为对象, 不存在的也可以创造出来, 面向对象的程序设计就好比如来设计西游记, 如来解决的问题是把经书传给
东土大唐, 如来想了想解决这个问题需要四个人, 唐僧,沙和尚,孙悟空,猪八戒. 每个人都有各自的特征和技能.(这
就是对象的概念,特征和技能分别对应对象的数据属性和方法属性), 然而这并不好玩,于是如来又安排了一群妖魔
鬼怪,为了防止师徒四人在取经路上被搞死,又安排了一群神仙保驾护航,这些都是对象,然后取经开始,师徒四人与
妖魔鬼怪神仙交互着直到最后取得真经,如来根本不会管师徒四人按照什么流程去取)
而面向对象的对象,是特征与技能的结合体,基于面向对象设计程序就好比在创造一个世界.你就是这个世界的上帝
存在的皆为对象,不存在的也可以创造出来,与面向过程机械式的思维方式形成鲜明的对比,面向对象更加注重对现
实世界的模拟,是一种'上帝式' 的思维方式,
优点 :解决了程序的扩展性,对某一个对象单独修改,会立刻反应到整个体系中,如对游戏中一个任务参数的特征和
技能修改都是很容易的
缺点 : 1. 编程的复杂度远高于面向过程, 不了解面向对象而立即上手基于它涉及程序,极容易出现涉及的问题,一
些扩展性要求低的场景使用面向对象会徒增编程难度,比如管理linux系统的脚本就不适合用面向对象去设计.面
向过程反而更加适合.
2. 无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就
由对象之间的交互解决问题,即便是上帝也无法准确地预测最终结果,于是我们经常看到对战类游戏,新增一个游戏
人物,在对战的过程中极容易出现阴霸的技能,一刀砍死三个人,这种情况无法准确预知的,只有对象之间交互,才能
准确地知道最终的结果.
应用场景 : 需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象
的程序设计大显身手的好地方.
面向对象的程序设计并不是全部,对于一个软件质量来说, 面向对象的程序设计只是用来解决扩展性...
二. 类与对象 :
1. 类即类别.种类, 是面向对象设计最重要的概念, 对象是特征与技能的结合体, 而类则是一系列对象相似的特征
与技能的结合体,
在现实世界中, 现有对象,再有类
世界上肯定是先出现各种各样的实际存在的物体, 然后随着人类文明的发展,人类站在不同的角度总结出了不同
的种类, 如人类, 动物类. 植物类等概念.
也就是说,对象是具体的存在, 而类仅仅只是一个概念,并不真实存在.
在程序中, 务必保证先定义类,后产生对象,
这与函数的使用是类似的, 先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类,不一样的是.
调用函数会执行函数体代码来返回的是函数体执行的结果,而调用类会产生对象,返回的是对象.
2. 类如何使用 :
在现实世界中,站在老男孩学校的角度 : 现有对象,再有类.
对象1:李坦克 特征: 学校=oldboy 姓名=李坦克 性别=男 年龄=18 技能: 学习 吃饭 睡觉 对象2:王大炮 特征: 学校=oldboy 姓名=王大炮 性别=女 年龄=38 技能: 学习 吃饭 睡觉 对象3:牛榴弹 特征: 学校=oldboy 姓名=牛榴弹 性别=男 年龄=78 技能: 学习 吃饭 睡觉 现实中的老男孩学生类 相似的特征: 学校=oldboy 相似的技能: 学习 吃饭 睡觉
在程序中, 务必保证:先定义(类).后使用(产生对象)
1. 在程序中特征用变量标识.技能用函数标识
2. 因而类中最常见的无非是 : 变量和函数的定义
程序中的类.
class OldboyStudent:
school = 'oldboy'
def learn(self)
print('is learning')
def eat(self)
print('is eating')
def sleep(self)
print('is sleeping')
注意 :
1. 类中可以有任意python代码.这些代码在类定义阶段便会执行.
2. 因而会产生新的名称空间, 用来存放类的变量名与函数, 可以通过oldboy.__dict__查看.
3. 对于经典类来说,我们可以通过该字典操作类名称空间的名字,(新式类有限制), 但python为我们专门提供了语法
4. 点是访问属性的语法,类中定义的名字,都是类的属性
#程序中类的用法 .:专门用来访问属性,本质操作的就是__dict__ OldboyStudent.school #等于经典类的操作OldboyStudent.__dict__['school'] OldboyStudent.school='Oldboy' #等于经典类的操作OldboyStudent.__dict__['school']='Oldboy' OldboyStudent.x=1 #等于经典类的操作OldboyStudent.__dict__['x']=1 del OldboyStudent.x #等于经典类的操作OldboyStudent.__dict__.pop('x') #程序中的对象 #调用类,或称为实例化,得到对象 s1=OldboyStudent() s2=OldboyStudent() s3=OldboyStudent() #如此,s1、s2、s3都一样了,而这三者除了相似的属性之外还各种不同的属性,这就用到了__init__ #注意:该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值 class OldboyStudent: ...... def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex ...... s1=OldboyStudent('李坦克','男',18) #先调用类产生空对象s1,然后调用OldboyStudent.__init__(s1,'李坦克','男',18) s2=OldboyStudent('王大炮','女',38) s3=OldboyStudent('牛榴弹','男',78) #程序中对象的用法 #执行__init__,s1.name='牛榴弹',很明显也会产生对象的名称空间 s2.__dict__ {'name': '王大炮', 'age': '女', 'sex': 38} s2.name #s2.__dict__['name'] s2.name='王三炮' #s2.__dict__['name']='王三炮' s2.course='python' #s2.__dict__['course']='python' del s2.course #s2.__dict__.pop('course')
3. __init__方法
强调:
1. 该方法内可以有任意的python代码
2. 一定不能有返回值
class People:
country = 'China'
x = 1
def __init__(obj,name,age,sex):
# if type(name) is not str:
raise TypError('名字必须是字符串类型')
obj.name = name
obj.age = age
obj.sex = sex
def run(self)
print('----->',self)
obj1 = People(3537,18,'male')
ps :
1. 站的角度不同, 定义出的类是截然不同的.
2. 现实中的类并不完全等于程序中的类, 比如现实中的公司类,在程序中有时需要拆分成部门类.业务类.
3. 有时为了编程需求, 程序中也可能会定义现实中不存在的类, 比如策略类,现实中并不存在,但是在程序中却是很常见
4. 属性查找 :
类有两种属性 : 数据属性和函数属性
1. 类的数据属性是所有对象共享的,
2. 类的函数属性是绑定给对象用的.
#类的数据属性是所有对象共享的,id都一样 print(id(OldboyStudent.school)) print(id(s1.school)) print(id(s2.school)) print(id(s3.school)) ''' 4377347328 4377347328 4377347328 4377347328 ''' #类的函数属性是绑定给对象使用的,obj.method称为绑定方法,内存地址都不一样 #ps:id是python的实现机制,并不能真实反映内存地址,如果有内存地址,还是以内存地址为准 print(OldboyStudent.learn) print(s1.learn) print(s2.learn) print(s3.learn) ''' <function OldboyStudent.learn at 0x1021329d8> <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x1021466d8>> <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x102146710>> <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x102146748>> '''
5. 绑定到对象的方法的特殊之处
class OldboyStudent: school='oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def learn(self): print('%s is learning' %self.name) #新增self.name def eat(self): print('%s is eating' %self.name) def sleep(self): print('%s is sleeping' %self.name) s1=OldboyStudent('李坦克','男',18) s2=OldboyStudent('王大炮','女',38) s3=OldboyStudent('牛榴弹','男',78)
类中定义的函数(没有被任何装饰器装饰的) 是类的函数属性, 类可以使用, 但必须遵循函数的参数规则, 有几个参数需要
就要传几个参数.
类中定义的函数(没有被任何装饰器装饰的),其实主要是给对象用的,而且是绑定到对象的,虽然所有对象指向的都是想用的
功能,但是绑定到不同的对象就是不同的绑定方法.
强调 : 绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,就会将'谁'本身当做第一个参数传给方法,即自动传值
(方法__init__也是一样的道理)
注意 : 绑定到对象的方法的这种自动传值的特征,决定了在类中定义的桉树都要默认写一个参数self, self可以是任意
名字,但是约定俗成写成self
类即类型:
提示: python的dass术语与c++有一定区别,与Modula-3更像.
python中一切皆对象, 且python3中类与类型是一个概念, 类型就是类
#类型dict就是类dict >>> list <class 'list'> #实例化的到3个对象l1,l2,l3 >>> l1=list() >>> l2=list() >>> l3=list() #三个对象都有绑定方法append,是相同的功能,但内存地址不同 >>> l1.append <built-in method append of list object at 0x10b482b48> >>> l2.append <built-in method append of list object at 0x10b482b88> >>> l3.append <built-in method append of list object at 0x10b482bc8> #操作绑定方法l1.append(3),就是在往l1添加3,绝对不会将3添加到l2或l3 >>> l1.append(3) >>> l1 [3] >>> l2 [] >>> l3 [] #调用类list.append(l3,111)等同于l3.append(111) >>> list.append(l3,111) #l3.append(111) >>> l3 [111]