第15讲 python面向对象-继承、多态

1、继承的概念

1)提高了代码的复用性
2)让类与类之间产生了关系,有了这个关系,才有了多态的特性
3)继承也是面向对象的三大特性之一

定义一个动物类
如何能让这个当前的动物类实现全部的功能
1)直接修改动物类,在这个类中添加我们需要的功能
2)可以直接创建一个新类
3)直接从动物类继承

在创建类的时候,如果我们省略父类则默认父类为object
所有类都继承object,object是所有类的父类

class Animal:
    def run(self):
        print('动物在跑')

    def sleep(self):
        print('动物在睡觉')

class Cat:
    def run(self):
        print('猫在跑')

   def sleep(self):
        print('猫在睡觉')    

class Cat(Animal):
    def speak(self):
        print('喵喵喵')
    pass

c = Cat()
print(c)
c.run()
c.sleep()
c.speak()

返回值
<main.Cat object at 0x0000022CEBD59A90>
动物在跑
动物在睡觉
喵喵喵

isinstance(),检查实例

r1 = isinstance(c,Cat)
r2 = isinstance(c,Animal)
print(r1,r2)
返回值:True True

issubclass(),子类检查

class Person():
    pass
print(issubclass(Person,object))
print('issubclass=',issubclass(Cat,Animal))

#返回值:
True
issubclass= TrueTrue True

2、重写

如果子类中有父类同名的方法,则通过子类的实例去调用该方法时,会调用子类的方法而不是父类的方法,这个特点也称之为我们所说的方法的重写(覆盖)

class Animal:
    def run(self):
        print('动物在跑')

   def sleep(self):
        print('动物在睡觉')

class Cat(Animal):
    先找自己,如果没有,再找父类
    def run(self):
        print('猫在跑')
        
   def speak(self):
        print('喵喵喵')
    pass
    
a = Animal()
a.run()
#返回值:动物在跑
c = Cat()
print(c)
c.run()

返回值:猫在跑

当我们调用一个对象的方法时,会优先去当前对象中去寻找是否有该方法,如果有则直接调用
如果没有,则去当前对象的父类中寻找,如果父类中有则直接调用
如果没有,则去父类对象的父类中去寻找,依次类推,直到找到object,如果没有则报错

class A(object):
    def text(self):
       print('AAA')

class B(A):
    def text(self):
        print('BBB')

class C(B):
    def text(self):
        print('CCC')

c = C()
c.text()

返回值:CCC

3、super()

class Animal:
    def __init__(self,name):
        self._name = name

   @property  #将方法转换为属性来调用
    def name(self):
        return self._name

   @name.setter
    def name(self,name):
        self._name = name

父类中的所有方法都会被子类中继承,包括特殊方法

class Cat(Animal):
    
    #我希望可以直接调用父类中的__init__方法来初始化父类中的属性
    #super()可以获得当前类的父类
    #通过super()返回对象调用父类方法时,不要传递self
    def __init__(self,name,age):
        super().__init__(name)
        self._name = name
        self._age = age
        
   def run(self):
        print('猫在跑')
        
   def speak(self):
        print('喵喵喵')
    
   @property
    def age(self):
        return self._age

   @age.setter
    def age(self,age):
        self._age = age

c = Cat('小白',5)
c.name = '加菲猫'
c.age = 8
print(c.name)
print(c.age)

返回值:
加菲猫
8

4、多重继承
bases
语法 类名.bases 这个方法可以获得当前类所有类的父类
python 支持多重继承,也就是我们可以为一个类同时制定多个父类
我们在开发的时候,尽量不用多重继承,原因是增加了代码的复杂程度
如果多个父类中出现重名的方法,则会先在第一个父类中寻找,然后在找第二个,然后再找第三个
而且后面覆盖前面

class A(object):
   #def text(self):
   
   #    print('AAA')
    pass

class B(object):
    def text(self):
        print('B中text方法')
    def text2(self):
        print('BBB')

class C(A,B):
    pass

print(B.__bases__)

返回值:(<class ‘object’>,)

c = C()
c.text()
返回值:B中text方法

5、多态
多态也是面向对象的三大特性之一
一个对象可以以不同的形态去呈现

鸭子类型
如果有一个东西,走路象鸭子,叫声象鸭子,它就是鸭子
多态使得我们编程更有灵活性

class A:

   def __init__(self,name):
        self._name = name

   @property
   def name(self):
        return self._name

   @name.setter
   def name(self,name):
        self._name = name

class B:
    def __init__(self,name):
        self._name = name

   @property
    def name(self):
        return self._name

   @name.setter
    def name(self,name):
        self._name = name

class C:
    pass

a = A(‘葫芦娃’)
b = B(‘钢铁侠’)
c = C()

def say(obj):
    print('您好%s'%obj.name)

say(a)

#返回值:您好葫芦娃
say(b)
#返回值:您好钢铁侠
say©
#say©报错,‘C’ object has no attribute ‘name’

def say2(obj):
    #做类型检查
    #违反了多态的函数只适用于一种类型的对象,无法处理其它类型的对象,这样会导致函数的实用性非常差
    if isinstance(obj,A):
        print('您好%s'%obj.name)

say2(a)
#返回值:您好葫芦娃

len()
之所以一个对象能够通过len()函数获取长度,是因为对象中具有一个特殊方法__len__
lst = [1,2,3]
s = ‘python’
print(len(lst))
print(len(s))
print(len(b))
#返回值:10

总结:
面向对象的三大特征 封装、继承、多态
封装 确保对象中数据的安全
继承 保证了对象的可扩展性
多态 保证了程序的灵活性

6、属性和方法

class A(object):
    #类属性 直接在类中定义的属性
    #类属性 可以通过类本身的实例访问
    #类属性 只能通过类对象来修改,无法通过实例对象来修改
    count = 0

   #实例属性通过实例对象添加的属性叫实例属性
   #实例属性 只能通过实例对象来访问和修改,但类对象无法访问和修改
    def __init__(self):
        self.name = '葫芦娃'

   #实例方法
    #在类中定义,以self为参数的方法都是实例方法
    #实例方法在调用时,Python会将调用的对象作为self传入
    #当通过类调用时,不会自动传入self
    def text(self):
        print('这是text方法',self)

   #类方法
    #在类的内部使用 @classmethod 来装饰的方法叫做类方法
    #类方法的第一个参数是cls 会被自动传递 cls是当前的类对象
    @classmethod
    def text2(cls):
        print('这是text2方法',cls)
        print(cls.count)

   #静态方法
    #在类中内部使用@staticmethod 来修饰的方法属于静态方法
    #静态方法不需要指定在任何默认的参数,静态方法可以通过类和实例调用
    #静态方法可以理解为保存到类中的一个函数
    @staticmethod
    def text3():
        print('text3执行了')

a = A()
a.count = 5
print(‘A’,A.count)
print(‘a’,a.count)
#返回值:0 5
A.count = 5
print(‘A’,A.name)
#报错:AttributeError: type object ‘A’ has no attribute ‘name’
print(‘a’,a.count)
#返回值:5 5
print(‘a’,a.count)
print(‘a’,a.name)
a.text()
#返回值:这是text方法 <main.A object at 0x0000018E47B8B1D0>
A.text()
#报错:TypeError: text() missing 1 required positional argument: ‘self’
A.text(a)
#返回值:这是text方法 <main.A object at 0x0000018E47B8B1D0>

a.text3()
#返回值:text3执行了
A.text3()
#返回值:text3执行了

发布了31 篇原创文章 · 获赞 0 · 访问量 354

猜你喜欢

转载自blog.csdn.net/weixin_38027481/article/details/102827443
今日推荐