面向对象的三大特征:
1.封装:就是把数据与功能都整合到一起。针对封装到对象或者类中的属性,可以严格控制对它们的访问
2.继承:继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,新建的类可以称为子类或派生类,父类又可以称为基类或超类
3.多态:多态指的是一类事物有多种形态,比如动物有多种形态:猫、狗、猪
继承与抽象
通过类的内置属性__bases__可以查看类继承的所有父类
子类可以继承父类所有的属性,因而继承可以用来解决类与类之间的代码重用性问题
class People: school='清华大学' def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age class Student(People): def choose(self): print('%s is choosing a course' %self.name) class Teacher(People): def teach(self): print('%s is teaching' %self.name) stu=Student('ldb','male',18) tea=Teacher('jason','male',20) stu.choose() print(stu.school) tea.teach() print(tea.school)
属性查找
有了继承关系,对象在查找属性时,先从对象自己的__dict__中找,如果没有则去子类中找,然后再去父类中找
class Foo: def f1(self): print('Foo.f1') def f2(self): print('Foo.f2') self.f1() class Bar(Foo): def f1(self): print('Bar.f1') b=Bar() b.f2() # Foo.f2 # Bar.f1
父类如果不想让子类覆盖自己的方法,可以采用双下划线开头的方式将方法设置为私有的
class Foo: def __f1(self): # 变形为_Foo__f1 print('Foo.f1') def f2(self): print('Foo.f2') # 变形为self._Foo__f1,因而只会调用自己所在的类中的方法 self.__f1() class Bar(Foo): def __f1(self): # 变形为_Bar__f1 print('Bar.f1') b=Bar() b.f2() # 在父类中找到f2方法,进而调用b._Foo_f1()方法,同样是在父类中找到该方法 # Foo.f2 # Foo.f1
继承原理
python会在mro列表上从左到又开始查找基类,直到找到第一个匹配这个属性的类为止
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类
class A(object): def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class D(B, C): pass obj = D() obj.test() # 结果为:from B print(D.mro()) # 新式类内置了mro方法可以查看线性列表的内容,经典类没有该内置方法 # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
多态与多态性
多态性指的是可以在不用考虑对象具体类型的情况下而直接使用对象,这就需要在设计时,把对象的使用方法统一成一种:列如,动物肯定有talk方法,于是我们可以不用它们具体是什么类型的动物,而直接使用