面向对象
- 
什么是面向过程 - 
自上而下顺序执行,逐步求精 
- 
其程序结构是按功能划分为若干个基本模块,这些就是树状结构 
- 
各模块之间的关系尽可能简单,在功能上相对独立 
- 
每一模块内部均是由顺序、选择和循环三种基本结构 
- 
其模块化实现的具体方法是使用子程序 
- 
程序流程在写程序时就决定了 
 
- 
- 
什么是面向对象 - 
把数据及对数据的操作方法放在一起,作为一个相互依赖的整体——对象 
- 
对同类对象抽象出其共性,形成类 
- 
类中的大多数数据,只能用本类的方法进行处理 
- 
类通过一个简单的外部接口与外界发生关系, 
- 
程序流程由用户在使用中决定 
 
- 
- 
理解面向对象 - 
面向对象是相对面对过程而言 
- 
面向对象和面向过程都是一种思想 
- 
面向过程 - 
强调的是功能行为 
- 
关注的是解决问题需要哪些步骤 
 
- 
- 
面向对象 - 
将功能封装进对象,强调具备了功能的对象 
- 
关系的是解决问题需要哪些对象 
 
- 
- 
面向对象是基于面向过程的 
 
- 
- 
面向对象的特点 - 
是一种符号人们思考习惯的思想 
- 
可以将复杂的事情简单化 
- 
将程序员从执行者转换成了指挥者 
- 
完成需求时 - 
先要去找具有所需的功能的对象来用 
- 
如果该对象不存在,那么创建一个具有所需功能的对象 
 
- 
 
- 
- 
类与对象的关系 - 
使用计算机语言就是在不断的在描述现实生活中的事物 
- 
Python中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义 
- 
对象即使该类事物实实在在存在的个体 
 
- 
- 
类的定义 - 
生活中描述事物无非就是描述事物的名称/属性/行为 
- 
python中用类来描述事物也是如此 - 
属性: 对应类中的成员变量 
- 
行为: 对应类中的成员方法 
 
- 
- 
定义类其实在定义类中的成员(成员变量和成员方法) 
- 
拥有相同(或者类似)属性和行为的对象都可以 
 
- 
- 
类的设计 - 
只关心3样东西 - 
事物名称(类名) : 人(Person) 
- 
属性: 身高(height) 、年龄(age) 
- 
行为(功能): 跑(run) 、打架(fight) 
 
- 
 
- 
- 
创建类 - 
设计类 - 
类名:见名知意,首字母大写,其他遵循驼峰原则 
- 
属性:见名知意,其他遵循驼峰原则 
- 
行为(方法/功能):见名知意,其他遵循驼峰原则 
 
- 
 
- 
- 
创建类 - 
类: 一种数据类型,本身并不占内存空间,跟所学过的number,string,boolean等类似。用类创建实例化对象(变量),对象占内存空间 - 
格式: - 
class 类名(父类列表): 
- 
属性 
- 
行为 
- 
定义一个简单的类 - 
object: 基类,超类,所有类的父类,一般没有合适的父类就写object 
- 
class Person(object): #定义属性(定义变量) name = "" age = 0 height = 0 weight = 0 #定义方法(定义函数) #注意: 方法的参数必须以self当第一个参数 #self 代表类的实例(某个对象) def run(self): print("run") def eat(self,food): print("eat" + food) def openDoor(self): print("我已经打开了冰箱门") def fillEle(self): print(“我已经把大象装进冰箱了”) def colseDoor(self): print("我已经关闭了冰箱门") def __ init__(self,name,age,height,weight) self.name = name self.age = age self.age = height self.age = weight self代表当前类创造的对象,然后把当前类创造的对象的属性值给修改了 def __ del__(self): print("这里是析构函数") 
 
- 
 
- 
 
- 
- 
使用类实列化对象 - 
实列化对象 - 
格式: 对象名 = 类名(参数列表) 
- 
注意: 没有参数,小括号也不能省略 
- 
per1 = Person() 
- 
per2 = Person() - 
per1和per2没有一点关系,仅仅类型相同 
 
- 
 
- 
 
- 
- 
访问对象的属性与方法 - 
访问属性 - 
格式: 对象名.属性名 
- 
赋值: 对象名.属性名 = 新值 
- 
per.name = "xiaoxin" per.age = 18 per.height = 160 per. weight = 42 
 
- 
- 
访问方法 - 
格式: 对象名.方法名(参数列表) 
- 
per.openDoor() per.fillEle() per.closeDoor() per.eat("apple") 
 
- 
- 
问题: 目前来看Person创建的所有对象属性都是一样的 
- 
对象的初始状态(构造函数) - 
构造函数: - 
__ init__() 在使用类创建对象的时候自动调用 
 
- 
- 
注意: 如果不显示的写出构造函数,默认会自动添加一个空的构造函数 
- 
per = Person("xiaoxin","18","160","140") __ init __函数里面的参数列表(形参)接受的值,是在构造对象的时候给Person的小括号传的值 
- 
以后我们就在__ init __里面定义属性了,这样我们创建出来的人就不一样了 
 
- 
 
- 
- 
self - 
self代表类的实例,而非类 
- 
哪个对象调用方法,那么该方法中的self就代表哪个对象(self就等价于per) 
- 
self.__ class__ 代表类名 
- 
#self不是关键字,换成其他的标识符也是可以的,但是帅的人都是用self 
 
- 
- 
析构函数 - 
__ del __() 释放对象时自动调用 
- 
per =Person() 
- 
del per 释放对象 
- 
对象释放以后就不能再访问了 
- 
在函数里定义的对象,会在结束时自动释放,这样可以用来减少内存空间的浪费 
 
- 
- 
重写 __ repr __ 与__ str__函数 - 
重写 :将函数重写定义写一遍 
- 
__ repr__() - 
给机器用的,在python解释器里面直接敲对面名在回车后调用的方法 
 
- 
- 
__ str__() - 
在调用print打印对象时自动调用,给用户用的,是一个描述对象的方法 
 
- 
- 
注意:在没有__ str __ 时 ,且有 __ repr __ , __ str__ = __ repr__ 
- 
优点: 当一个对象的属性值很多,并且都需要打印,重写了 __ str __ 方法后,简化了代码 
 
- 
- 
访问限制 - 
如果 要让内部的属性不被外部直接访问,在属性前加两个下划线( __ ),在python中如果在属性前加两个下划线,那么这个属性就变成了私有属性 
- 
外部不能使用,在类的内部可以使用,我们可以通过类的内部的方法,去修改私有属性 - 
所以我们可以在类的内部定义两个函数,一个赋值,一个取值 
 
- 
- 
可以通过类的内部自定义的方法实现对私有属性的赋值与取值 
- 
外部不能直接访问per.__ money 是因为Python 解释器把 _Person __ money,但是仍然可以用 _ Person __money 去访问,但是强烈建议不要这么干(帅的人都不这么干),不同的解释器可能存在解释的变量名不一致 
- 
在Python中 __ XXX__属于特殊变量,可以直接访问 
- 
在Python中 _XXX 变量, 这样的实例变量外部是可以访问的,但是,按照约定的规则,当我们看到这样的变量时,意思是"虽然我可以被访问,但是请把我视为私有变量,不要直接访问我" 
 
- 
- 
继承 - 
有两个类,A类和B类,当我们说A类继承自B类的时候,那么A类就拥有B类中的所有的属性和方法 
- 
object类是所有类的父类,还可以称为基类或超类 
- 
注意:继承者称为子类,被继承者称为父类 
- 
继承的作用 - 
优点 - 
简化了代码,减少冗余 
- 
提高了代码健壮性 
- 
提高了代码的安全性 
- 
是多态的前提 
 
- 
- 
缺点: - 
耦合与内聚是描述类与类之间的关系的。耦合性越低,内聚性越高,代码越好 
 
- 
 
- 
- 
单继承的实现 - 
详细见代码 
 
- 
- 
多继承的实现 - 
在子类中调用父类的初始化方法格式就是: 父类名. init(self) 
- 
super().__ init __ (父类中的属性)相对于类名 . __ init__,在单继承上用法基本无差 
 
- 
- 
多态 - 
一种事物的多种形态 
- 
最终目标:人可以喂任何一种动物 
 
- 
 
- 
 
- 
- 
对象属性与类属性 - 
class Person(object) #这里的属性实际上属于类属性(用类名来调用) name = “person” def __ init __(self,name) #对象属性 self.name = name 
 Person.name # 可以这样调用 输出person per = Person("tom") #对象属性的优先级高于类属性 per.name 输出tom #动态的给对象添加对象属性 per.age = 18 #只针对于当前对象生效,对于类创建的其他对象没有作用 Person.name 输出person per2 = Person("lilei") per2.age #没有age属性
- 
del per.name #删除对象中的那么属性,在调用会使用到同名的类属性 
- 
注意:以后千万不要将对象属性与类属性重名,因为对象属性会屏蔽掉类属性。但是当删除对象属性后,在使用又能使用类属性了 
 
- 
- 
动态给实例添加属性和方法并使用 __ slots__ - 
#创建一个空类 
- 
class Person(object): __ slots__("name","age") #现在只能给Person对象添加这两个属性 per = Person() #动态添加属性,这体现了动态语言的特点(灵活) per.name = "tom" #动态添加方法 引入模块 from types import MethodType def say(self): print("my name is " + self.name) 
 per.speak = MethodType(say,per) #将say函数 添加给per对象里面的speak per.speak() #调用方法
- 
如果我们想要限制实例的属性怎么办? - 
比如,只允许给对象添加,name,age,height,weight属性 
- 
解决:定义类的时候,定义一个特殊的属性(__ slots __), 可以限制动态添加的属性 - 
比如在定义类的时候 写 - 
__ slots__("name","age") #现在只能给Person对象添加这两个属性 
 
- 
 
- 
 
- 
 
- 
- 
@property方法的使用 - 
class Person(object) def __ init __(self,age) #属性直接对外暴露 #self.age = age #限制访问 self__ age = age #方法名为受限制的变量去掉双下划线 @property def age(self): return self.__age @age.setter #去掉下划线.setter 给self.__age进行赋值 def age(self,age) if age <0 : age = 0 self.__age = age def getAge(self): return self.__age def setAge = (self,age) if age<0: age = 0 self.__age = age per = Person(18) 属性直接对外暴露,不安全,没有数据的过滤 per.age = -10 使用限制访问,需要自己写set和get方法才能访问 per.setAge(15) per.getAge() 输出15 per.age = 100 # 相当于调用setAge per.age 就输出100 #相当于调用 getAge @property 可以让你对受限制访问的属性使用点语法 
 
- 
- 
运算符重载 - 
不同的类型用加法会有不同的解释 class Person(object) def __ init__(self,num): self.num = num def __ add __(self,other): return Person(self.num + other.num) def __ str__(self): return "num = " + str(self.num) per1 = Person(1) per2 = Person(2) print(per1+per2) 输出3 per1+per2 === per1. __ add __(per2) 
 
- 
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号