封装
是面向对象编程的三大特征之一,将属性和方法 封装 到一个抽象的类对象中,在方法内部对属性进行操作,在类对象外部调用方法
class Student(object):
def __init__(self):
self.__score = 90
def get_score(self):
return self.__score
def set_score(self, score):
if 0<=score<=100:
self.__score = score
else:
raise ValueError("成绩必须在0~100之间")
s = Student()
s.get_score()
>
>
90
s = Student()
s.set_score(88)
print(s.get_score())
>
>
88
继承
主要体现是实现代码的 重用,相同的代码不需要重复的编写;
子类可以在父类功能上进行重写,扩展类的功能。
单继承:子类只有一个直接父类时称为单继承
多继承:子类有多个直接父类时称为多继承
子类会继承父类(包括直接和间接父类)的所有属性和方法
class Animal(object):
def eat(self):
print("吃饭")
def drink(self):
print("喝水")
class Dog(Animal):
def swim(self):
print("游泳")
class Bird(Animal):
def fly(self):
print("飞翔")
dog = Dog()
dog.eat()
dog.drink()
dog.swim()
>
>
吃饭
喝水
游泳
bird = Bird()
bird.eat()
bird.drink()
bird.fly()
>
>
吃饭
喝水
飞翔
重写
如果子类对继承父类的某个属性或方法不满意,可以在子类中对其进行重写从而提供自定义的实现,重写的方式为:在子类中定义与父类中同名的属性或方法(包括装饰器)
子类重写父类的属性后,通过子类或其实例对象只能访问重写后的属性,而无法访问被重写的父类的属性
子类重写父类的方法后,通过子类或其实例对象只能访问重写后的方法,而无法访问被重写的父类的方法
class ParentClass(object):
ca = "ca(父类)"
def __init__(self):
print("__init__()被调用了(父类)")
def im(self):
print("im()被调用了(父类)")
@classmethod
def cm(cls):
print("cm()被调用了(父类)")
class ChildClass(ParentClass):
ca = "ca(子类)"
def __init__(self):
print("__init__()被调用了(子类)")
def im(self):
print("im()被调用了(子类)")
@classmethod
def cm(cls):
print("cm()被调用了(子类)")
cc = ChildClass()
print(ChildClass.ca)
print(cc.ca)
cc.im()
ChildClass.cm()
cc.cm()
>
>
__init__()被调用了(子类)
ca(子类)
ca(子类)
im()被调用了(子类)
cm()被调用了(子类)
cm()被调用了(子类)
父类中被重写的名为xxx的方法,在子类重写后的方法中可以通过super().xxx()进行调用
class ChildClass(ParentClass):
ca = "ca(子类)"
def __init__(self):
super().__init__()
print("__init__()被调用了(子类)")
def im(self):
super().im()
print("im()被调用了(子类)")
@classmethod
def cm(cls):
super().cm()
print("cm()被调用了(子类)")
cc = ChildClass()
print(ChildClass.ca)
print(cc.ca)
cc.im()
ChildClass.cm()
cc.cm()
>
>
__init__()被调用了(父类)
__init__()被调用了(子类)
ca(子类)
ca(子类)
im()被调用了(父类)
im()被调用了(子类)
cm()被调用了(父类)
cm()被调用了(子类)
cm()被调用了(父类)
cm()被调用了(子类)
MRO(方法解析顺序)
对于支持继承的编程语言来说,其方法(属性)可能定义在当前类,也可能来自于基类,所以在方法调用时就需要对当前类和基类进行搜索以确定方法所在的位置。而搜索的顺序就是所谓的「方法解析顺序」(Method Resolution Order,或MRO)
class A(object):
def f(self):
print("A.f")
class B(A):
def f(self):
print("B.f")
class C(A):
def f(self):
print("C.f")
class D(B, C):
def f(self):
print("D.f")
d = D()
d.f()
>
>
D.f
class A(object):
def f(self):
print("A.f")
class B(A):
pass
class C(A):
def f(self):
print("C.f")
class D(B, C):
pass
#pass可以理解为跳过的意思
d = D()
d.f()
>
>
C.f
对于一颗类继承树,可以调用最底层类对象的方法mro()或访问最底层类对象的特殊属性__mro__
print(D.mro())
>
>
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
如果想调用指定父类中被重写的方法,可以给super()传入两个实参:super(a_type, obj),其中obj所对应类对象的MRO中,a_type后面的那个类对象
class A(object):
def f(self):
print("A.f")
class B(A):
def f(self):
print("B.f")
class C(A):
def f(self):
print("C.f")
class D(B, C):
def f(self):
super(B,self).f()
d = D()
d.f()
>
>
C.f()
多态
一种接口多种实现,实现接口的重用。简单的说多态就是“具有多种形态”
class Q(object):
def r(self):
print("666")
class W(Q):
def r(self):
print("777")
class E(Q):
def r(self):
print("888")
def t(y):
y.r()
t(Q())
t(W())
t(E())
>
>
666
777
888