面向对象编程
- OO面向对象
- OOA面向对象的分析
- OOD面向对象的设计
- OOI面向对象的实现
- OOP面向对象的编程
OOA --> OOD --> OOI :实现过程通过OOP进行
类
– 类中的个体是一个个单独对象
– 表明事物的特征,属性(变量)
– 表明事物功能与动作,成员方法(函数)
- 类命名规范:遵循变量命名规范;大驼峰
- 成员属性直接赋值变量,可用none
– 访问对象成员:obj.成员属性名称 obj.成员方法
– 对象所有成员检查:obj. __ dict __
– 类所有成员:classname. __ dict __
– 类和对象的成员分析:
- 类和对象都可以储存成员,成员可以归类所有,也可以归对象所有
- 类储存成员使用的是与类关联的一个对象
- 独享储存成员是储存在当前对象中
- 对象访问一个成员时,如果对象中没有该成员,尝试访问类中的同名成员,如果对象中有此成员,一定使用对象中的成员
- 创建对象的时候,类中行的成员不会放入对象当中,而是得到一个空对象没有成员
- 通过对象对类中成员重新赋值或者通过对象添加成员时,对应成员会保存在对象中,而不会修改类成员
— self / cls:
- self在对象的方法中表示当前对象本身,如果通过对象调用一个方法,那么该对象会自动传入到当前方的第一个参数中
- self并不是关键字,只是一个用于接收对象的普通参数
- 方法中有self形参的方法成为非绑定类的方法,可以通过对象访问,没有self的是绑定类的方法,只能通过类访问
- cls就是类本身
class A():
name = "axin"
age = 18
def __init__(self):
self.name = "ashui"
self.age = 200
def say(self):
print(self.name)
print(self.age)
class B():
name = "pass"
age = 90
a = A()#此时,系统会默认把a作为第一个参数传入函数
a.say()
A.say(a)#此时,self被a替换
A.say(A)#同样可以把A传入参数
A.say(B)#传入实例B,但B具有name和age属性,所以可执行
– 构造函数:
- __ init __
- 实例化的时候,系统自动第一个调用的函数,进行初始化
- 继承中构造函数先找本类,没有的话一级一级找,找到则停止
def __init__(self):
pass
面向对象三大特性
- 封装
- 继承
- 多态
– 封装:对类中对象的成员进行访问限制
-
三个级别:公开public 受保护protected 私有的private
-
判别对象的位置:对象内部,对象外部,子类中
-
私有封装:最高级别封装,只能当前类或对象(成员前加两个下划线)
class Peraon():
name = "a"
__age = 18 #此为私有 通过改名策略禁止外部访问
- 受保护封装:一定级别封装,类中或者子类中都可以访问,外部不可以访问,成员命名前加一个下划线
- 公开的:未封装,任何地方可以访问
– 继承
- 一个类可以获得另外一个类中的成员属性和方法的行为
- 可减少代码,增加复用,设置类与类直接的关系
- 父类(基类、超类)除私有之外都被子类(派生类)继承is-a
- 子类继承父类后并没有将父类成员完全复制到子类中,而是访问调用
- 子类中成员如果和父类相同,优先使用子类
- 子类如果想扩充父类的方法,可以在定义新方法的同时访问父类成员进行访问(例1)
- class 子类(父类,默认object):
- super不是关键字,是获取MRO(.__ mro __可以查血统)列表中第一个类
- 单继承或多继承(java不允许,Python采用c3算法) 菱形继承钻石继承问题 具体描述与避免
例1
class A():
name = "axin"
age = 18
def say(self):
print(self.name)
print(self.age)
class B(A):
def do(self):
print("I love running")
def all(self):
A.say(self)
# ↑调用父类的函数进行扩充父类函数功能,使用spuer().say()也可以
self.do()
c = B()
c.all()
- 继承变量查找顺序:优先查找自己的变量,然后父类,构造函数有定义,则不在向上查找
– 多态
- 同一个对象在不同情况下有不同的状态出现
- python中是一种思想,c++java中是语法
- 多态性:一种调用方式,不同执行效果
- mixin:使用多继承语法来实现类的功能扩展mixin介绍
–使用mixin可以在不对类进行修改的情况下扩展功能
–可以方便组织和维护不同功能组件划分
–可以避免很多类从而导致的继承混乱
类相关函数
- issubclass(B,A)判断b是否是a的子类
- isinetance(b,B)判断b是否是B的实例
- hasattr(a,“name”)判断对象s是否有name成员
- dir(a)获取对象a的成员列表
- getattr(a,name,100)获取对象a的name成员,如果没有返回100
- setattr(b,name,ppp)修改或增加对象b的name成员为ppp
- delattr(a,name)删除对象a的name成员
类的成员描述符
- 为了在类中对类的成员属性进行相关操作的而创建的一种方式(赋值,读取,删除)
–get获取属性
–set修改或者添加属性
–delete删除属性 - 类的成员描述符包含:
–类实现描述符,多个类的多个成员属性共用一个描述符
–属性修饰符,当前类的一个成员属性
– property(fget,fdel,doc)对一个类中多个成员属性进行控制
class Students():
def fget(self):
return self._name * 2
def fset(self,name):
self._name = name.upper()
def fdel(self):
self._name = "NoName"
name = property(fget,fset,fdel,"这段是说明文档")#对name进行操作
a = Students()
a.name = "hahahahaha"
print(a.name)
类的成员属性
- __ dict __字典方式现实类的成员组成
- __ doc __获取类的文档信息
- __ name __获取类的名称
- __ bases __获取类的所有父类,元组方式展现
类的魔术函数
- 不需要人为调用,特定时刻自动触发
- 用两个下划线包裹名称 例 __ init __ /__ call __
- 系统已经规定好了各个魔术函数何时触发
- __ init __ /__ new __
- __ call __
- __ str __ / __ repr __
- __ set __ / __ get __ / __ delete __
- __ getattr __(访问不存在的属性时) / __ setattr __
- __ gt __(运算类触发)等等
- 触发例子
class A():
def __init__(self):
print("-------")
def __call__(self):
print("我被调用了") #a被当作函数时,触发此函数
def __str__(self):
return "我变成了字符串"#a被当作字符串时,触发此函数
a = A()
a()#a当作函数
print(a)#a当作字符串
- __ setattr __防止死循环例子
class A():
def __setattr__(self,name,value):
print("设置属性:",name)
#self.name = value 这句会导致卡死,改为:
super().__setattr__(name,value)
p = A()
p.age = 18
类跟对象的三种方法
-
实例方法
–需要实例化对象才能使用的方法,使用过程中可能需要截止对象的其他对象的方法完成 -
静态方法
–不需要实例化,通过类直接访问 -
类方法
–不需要实例化
class person():
def eat(self):#实例方法
print(self,"eating")
@classmethod
def play(cls):#类方法
print(cls,"playing")
@staticmethod
def say():#静态方法
print("saying")
a = person()
a.eat()
person.play()
a.play()
person.say()
a.say()
#都可以被实例调用
抽象类
- 抽象方法:没有具体实现内容的方法
- 抽象方法的主要意义是规范了子类的行为和接口
- 抽象类的使用需要借助abc模块
- 包含抽象方法的类,通常称为abc类
- 抽象类的使用:
–抽象类可以包含抽象方法,也可包含具体方法
–抽象类中可以有方法也可以有属性
–抽象类不允许直接实例化
–必须继承才可以使用,且继承的子类必须实现所有继承来的抽象方法 - 界定子类没有事项所有继承的抽象方法,则子类也不能实例化
- 抽象类的主要作用是设定类的标准,以便于开发的时候具有统一的规范
#抽象类
import abc
class Preson(metaclass =abc.ABCMeta):
#定义一个抽象的方法
@abc.abstractmethod
def smoking(self):
pass
#定义类的抽象方法
@abc.abstractclassmethod
def drink():
pass
#定义静态抽象的方法
@abc.abstractstaticmethod
def play():
pass
def sleep(self):
print("sleeping")
元类
- 写法固定,必须继承于type命名metaclass结尾
- 就是一个类的模板
- 收藏夹有详细文章