面向对象
Posted fengzi759
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象相关的知识,希望对你有一定的参考价值。
-
什么是面向过程
-
自上而下顺序执行,逐步求精
-
其程序结构是按功能划分为若干个基本模块,这些就是树状结构
-
各模块之间的关系尽可能简单,在功能上相对独立
-
每一模块内部均是由顺序、选择和循环三种基本结构
-
其模块化实现的具体方法是使用子程序
-
程序流程在写程序时就决定了
-
-
什么是面向对象
-
把数据及对数据的操作方法放在一起,作为一个相互依赖的整体——对象
-
对同类对象抽象出其共性,形成类
-
类中的大多数数据,只能用本类的方法进行处理
-
类通过一个简单的外部接口与外界发生关系,
-
程序流程由用户在使用中决定
-
-
理解面向对象
-
面向对象是相对面对过程而言
-
面向对象和面向过程都是一种思想
-
面向过程
-
强调的是功能行为
-
关注的是解决问题需要哪些步骤
-
-
面向对象
-
将功能封装进对象,强调具备了功能的对象
-
关系的是解决问题需要哪些对象
-
-
面向对象是基于面向过程的
-
-
面向对象的特点
-
是一种符号人们思考习惯的思想
-
可以将复杂的事情简单化
-
将程序员从执行者转换成了指挥者
-
完成需求时
-
先要去找具有所需的功能的对象来用
-
如果该对象不存在,那么创建一个具有所需功能的对象
-
-
-
类与对象的关系
-
使用计算机语言就是在不断的在描述现实生活中的事物
-
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
-
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)
-
以上是关于面向对象的主要内容,如果未能解决你的问题,请参考以下文章