10.python-OOP面向对象

面向对象编程

  • 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结尾
  • 就是一个类的模板
  • 收藏夹有详细文章
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值