面向对象基础总结

继承

什么是继承?

继承是一种新建类的方式 新建类称为 子类 /派生类 被继承的类称之为 父类/基类/超类

继承的 特性: 子类可以遗传/重用父类的属性

1.python中一个子类可以同时继承多个父类

2.在继承背景下说 python中的类分为 两种,新式类,经典类

新式类:但凡继承了object的类 以及该类的子类 都是 新式类(可以用到 object的方法)在python中一个类即便是没有显示的继承任何类 默认就会继承object

​ 经典类:没有继承object的类,以及该类的子类 .. 都是经典类 python2 中才会区分新式类和经典类 在python中一个类即便是没有显示的继承任何类 也不会继承object

class Foo(object):  python3和python2 中都可以用的新式类
    pass

print(Foo.__bases__) # 查看基类符 父类

为何要是用继承?

减少类与类之间的代码冗余

class Foo(object):
    x = 111

class Sub(Foo):
    x = 222
f = Sub()
f.x = 333
print(f.x)

在子类派生的新方法中重用父类功能的方式一

指名道姓的方式: 指名道姓的引用某一个;类的函数
    # 总结 和继承没有关系 2.访问的是类的函数 没有自动传值得效果
class Oldboy:
    def __init__(self, name, age, sex):
        self.name = name 
        self.age = age 
        self.sex = sex
        
class Student(Oldboy):
    def __init__(self,name, age, sex, score):
        Oldboy.__init__(self,name, age, sex)
        self.score = score

菱形继承问题:

新式类:广度优先,从左往右一个分支一个分支的查找,最后一个分支才去顶级查找

经典类:深度优先查找,从左往右有个分支一个分支的查找,在第一个分支就去顶级查找

 f.mto() #等于f.__mro__ 查看顺序 mro列表就是一个简单的所有基类的线性顺序
class A:
    pass

class B(A):
    pass

class C(B):
    pass

print(C.mro())

# [<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

在子类派生的新方法中重用父类功能的方式二super

super(自己的类名,自己的  对象)必须在类中使用
#在python2中 :super(自己的类名,自己的对象)
#在python3中 :super()
#调用该函数会得到一个返回值 是一个特殊的对象 对象访问一个功能 就是绑定方法 自动传值  该对象专门用来父类中的属性!!!
                             
完全参照mro列表查找    严格依赖继承 mro列表 访问的是一个绑定方法 有自动传值的方法

class Oldboy:
    def __init__(self, name, age, sex):
        self.name = name 
        self.age = age 
        self.sex = sex
        
class Student(Oldboy):
    def __init__(self,name, age, sex, score):
        
        Oldboy.__init__(self,name, age, sex)
        super(Oldboy,self).__init__(name, age, sex)
        super().__init__(name, age, sex) 
        
        self.score = score


组合

组合指的是某一个对象拥有一个属性,这个属性是另外一个类的对象

多态

什么是多态?

同一种事物分不同的形态

class Animal: #动物有了就全都有了
    def speak(self):
        pass
class dog(Animal):
    pass
class pig(Animal):
    pass
class people(Animal):
    pass
obj = dog()
obj1 = pig()
obj2 = people()

obj.speak()
obj1.speak()
obj2.speak()

为什么使用多态

多态性:在多态的背景下,可以不用考虑对象具体类型的前提下而直接使用对象

模块abc 强制子类遵循父类的规范

 import abc
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def speak(self):
        pass

class People(Animal):
    def speak(self):
        print('say helllo')


class pig(Animal):
    def speak(self):
        print('henehnehen')


class dog(Animal):
    def speak(self):
        print('wannwanwna')

obj = People()
obj2 = pig()
obj3 = dog()

python中 不推崇限制你 崇尚鸭子类型 只要你长得像 你就是

封装

什么是封装? 装 :往名称空间里/容器里存入名字

封: 代表 将存放于名称空间的名字隐藏起来 对外 不对内

如何装?

在类定的属性前加__开头 没有结尾 (****)

class A:
    __x = 123
    def __init__(self, name, age):
        self.__name = name
        self.__age = age
    def get__(self):  #通过函数是可以访问的
        print(self.__name, self.__age)
        
# 对外隐藏  内部是可以访问到的

#__ 到底如何实现了隐藏 
只要是__开头的 他就会把你的开头改成  _A__X : 123 仅仅只是语法意义上的变形 并不会真正的限制类外部的访问

#如何实现的对外隐藏 对内开放
改变形操作 只会在类定义阶段 检测语法时 执行一次,类定义阶段之后新增的__开头的属性并不会变形  

为什么要封装?

封数据属性 : 将数据属性隐藏起来 类外部无法直接操作属性 需要类内部开辟一个接口 可以使外部间接的操作属性 (可以在接口上定义任意的控制逻辑 从而严格的控制属性)

封函数属性 :隔离复杂度 还是不能直接给外部使用 需要开个接口来调用

property装饰器 是用来将类中的函数属性装饰成数据属性

class D:
    def __init__(self, name, height, weight):
        self.__name = name
        self.height = height 
        self.weight = weight
	@property
    def bim(self):
        return self.weight / (self.height**2)
     
    @bin.setter
    def bin(self,obj)
        if type(obj) is not str:
            print('输入字符串呀')
    	self.__name == obj
       
    @bin.deleter
    def bin(self)
    	del self.__name
  
  s = D()
s.bim  #就可以调用了
s.bim = 'engon'
del s.bin

bin = property(get_bin, set_bin, del_bin)


绑定方法 与 非绑定方法

两大类 三小种

绑定方法 绑定给谁 就会把谁当做第一个参数传入

绑定给对象的 类中定义的函数都是绑定给对象的

classmethod 会将类作为第一个参数自动传入 (需要类名或其他 )

staticmethod 非绑定方法 既不与类绑定 又不与对象绑定 普通函数没有自动传值的效果

class A:
	def index(self):
		print('我是对象绑定')
		
	@classmethod
	def f2 (cls):
		print('我是绑定给类的')
import uuid 
uuid.uuid4()  生成一个第一无二的编号

面向对象高级(边边脚脚)

isinstance () 判断一个对象是否是一个类的实例 返回true false

print(isinstance([1,23,4], list))

issubclass() 判断是否是子类 (父类, 子类)

反射 属性操作 通过字符串 反射或者映射到对象或者类的属性上

hasarrt 本质 'name' in obj.__dict __判断有没有

getattr 本质 obj.dict['name'] 获取属性的值 没有报错 第三个参数有的话找不到返回

setattr 设置值 修改值 setattr(obj,'name', 'egon') 存在修改 不存在 添加

delattr delattr(obj, 'name') 删除

内置方法 str del

# 内置方法是  满足某种条件下自动触发
__str__ 在对象被打印时自动触发,可以用来定义对象被打印时的输出信息
__del__ 在对象被删除时先自动触发  可以用来回收对象以外的其他相关资源 
__call__ (self, *args, **kwargs)  在对象被调用时先自动触发  可以用来回收对象以外的其他相关资源 
posted @ 2019-07-30 00:15  LD_Dragon  阅读(189)  评论(0编辑  收藏  举报