python 中面向对象的基础

面向对象的三大特征:继承、封装和多态

封装:把内容封装到某个地方,便于后面使用; 对于封装,其实就是使用初始化构造方法将内容封装到对象中,然后通过对象直接或者self来获取被封装的内容;
继承:儿子可以继承父亲的内容【属性和行为】(爸爸有的儿子都有,但是儿子有的爸爸不一定有);
多态:定义时的类型和运行时的类型不一样,此时就成为多态;

单继承
class Animal:  # 父类
    def eat(self):
        print('吃饭')
        pass
    def drink(self):
        pass
    pass


class Dog(Animal):  # 继承 Animal -- 只需要类名后面的小括号()中写上父类的名字,那么父类的属性、方法,会被继承给子类
    def wwj(self):
        print('小狗汪汪叫')
        pass
    pass


class Cat(Animal): # 继承 Animal -- 父类的属性、方法,会被继承给子类
    def mmj(self):
        print('小猫喵喵叫')
        pass
    pass


d1=Dog()
d1.eat()  # 继承了父类的行为 -- # 单继承,只用关注不一样的就行了,一样的就用父类继承过来
d1.wwj()

c1=Cat()
c1.eat() # 继承了父类的行为
c1.mmj()
多继承

子类可以继承一个父类,那是否可以继承两个父类或多个呢? 答案是肯定的,这就是python的多继承;
C 类可以继承 A、B 两个类,可以将 A, B 中的方法继承过来,C 拥有 A,B 的方法和属性,class C(A, B);
如果在上面的 A 类和 B 类中,有一个同名的方法,那么通过子类去调用的时候, 查找顺序是:
先在 C 中找 -> 没有 -> 去 A 中找 -> 再没有 -> 去 B 中找 -> B有输出,查找中断,不再继续 -> 若 B 中也没有会报错;

class D():
    def eat(self):
        print('D.eat')


class C(D):
    def eat(self):
        print('c.eat')


class B(D):
    def eat(self):
        print('B.eat')

        
class A(B,C):  # 多继承
    pass

a = A()
a.eat()  # 执行 eat 时,查找的顺序是:A -> B -> C -> D
print(A.__mro__)  # 查询查找的顺序,也是继承的顺序,若是都有同名方法的话,那就是重载了 -- 为了方便且快速地看清 继承 关系和顺序,可以用__mro__方法
继承的传递

类的传递过程中,我们又把父类称为基类,子类又称为派生类,父类的属性和方法可以一级一级的传递到子类,子类可以继承父类的父类的方法和属性;

class Grandfather:
    def eat(self):
        print('吃饭')


class Father(grandfather):
    pass


class Son(father):
    pass


s=Son()
s.eat()
print(Son.__mro__)
重写父类方法

子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法;通常都是父类方法已经不能满足子类的需求,需要重写或完善父类;

class Dog:
    def bark(self):
        print('汪汪叫')


class Keji(Dog):
    def bark(self):  # 重写父类方法
        print('像小猫一样叫。')


kj = Keji()
kj.bark()
调用父类方法--继承+扩展

若子类中将有一个方法需要父类的功能,并且在此之上添加新的功能;如果直接重写父类方法,那么就要重复写很多代码,这里可以先调用父类方法再添加新的;

class Dog:
    def __init__(self,name,color):
        self.name = name
        self.color = color
        
    def bark(self):
        print('汪汪叫')


class Keji(Dog):
    def __init__(self,name,color):  # 重写父类的方法
        # Dog.__init__(self,name,color)  # 1、手动调用父类的方法,执行完毕就可以具备 name 和 color 这两个实例属性了
        super().__init__(name,color)  # 2、自动调用,会自己找到对应的父类 self,多个父类的时候会按照顺序查找
        self.height=90  # 3.扩展其他属性
        self.weight=20

    def __str__(self):
        return '{}的颜色是{},它的身高是{}cm,体重是{}公斤'.format(self.name,self.color,self.height,self.weight)
    
    def bark(self):  # 属于重写父类方法
        print('像小猫一样叫。')
        
        
kj = keji('柯基犬','红色')
kj.bark()
print(kj)
多态--多种形态

又称鸭子模型,定义时的类型和运行时的类型不一样,对同一种行为,不同的子类【对象】有多种不同的表现
两个前提:1.继承:必须存在继承关系,必须在父类和子类之间;2.重写:子类重写父类的方法;
多态的优势:增加程序的灵活性;增加程序的扩展性;

class Animal:  # 父类    
    def say_who(self):  # 说话的行为
        print('我是一只动物')
        
        
class duck(Animal):  # 子类:鸭子类
    def say_who(self):  # 子类重写父类的方法
        print('我是一只鸭子')
        
        
class dog(Animal):  # 子类:小狗类    
    def say_who(self):
        print('我是一只小狗')

        
class cat(Animal):  # 子类:小猫类
    def say_who(self):
        print('我是一只小猫')

        
print('*****重写调用****')
yz=duck()
yz.say_who()

xg=dog()
xg.say_who()

xm=cat()
xm.say_who()

print('********循环调用(多态的优势)****')  # 新增子类更方便
class bird(Animal):  # 子类:小鸟类
    def say_who(self):
        print('我是一只小鸟')
        

def commmon(obj):  # 多态可以有个 统一调用的方法
    '''
    :param obj: 对象的实例
    :return:
    '''
    obj.say_who()
    
listobj = [duck(), dog(), cat(), bird()]

for i in listobj:
    commmon(i)  # 我是一只鸭子, 我是一只小狗, 我是一只小猫, 我是一只小鸟
posted @ 2022-03-09 17:08  应当如次  阅读(53)  评论(0)    收藏  举报
回到顶部