面向对象:继承,知识点补充

Posted xiaomage666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象:继承,知识点补充相关的知识,希望对你有一定的参考价值。

面向对象:

? 三大特性 : 继承 封装 多态

什么是继承:
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类。
python中类的继承分为:单继承和多继承。

? 在开发程序的过程中,如果我们定义了一个类A,然后又想新建立另外一个类B,但是类B的大部分内容与类A的相同时,我们不可能从头开始写一个类B,这就用到了类的继承的概念。
通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用。
? 用已经有的类建立一个新的类,这样就重用了已经有的软件中的一部分设置大部分,大大节省了编程工作量,这就是常说的软件重用,不仅可以重用自己的类,也可以继承别人的,比如标准库,来定制新的数据类型,这样就是大大缩短了软件开发周期,对大型软件开发来说,意义重大.

? 通过继承建立了派生类与基类之间的关系,它是一种‘是‘的关系,比如白马是马,人是动物。当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如教授是老师。

引入:继承与重用性
        猫:
            吃  (方法名)
            喝
            睡
            爬树
        狗:
            吃
            喝
            睡
            看家
    #如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,代码如下:
        class Cat:
            def __init__(self,name):
                self.name = name
            def eat(self):
                print(f'self.name is eating ')
            def drink(self):
                print(f'self.name is drinking ')
            def sleep(self):
                print(f'self.name is sleeping ')
            def climb_tree(self):
                print(f'self.name is climbing ')
            #类名在最后指向空间地址

        class Dog:
            def __init__(self,name):
                self.name = name
            def eat(self):
                print(f'self.name is eating ')
            def drink(self):
                print(f'self.name is drinking ')
            def sleep(self):
                print(f'self.name is sleeping ')
            def house_keep(self):
                print(f'self.name is keeping the house ')

        小白 = Cat('小白')
        小白.eat()
        小白.drink()
        小白.sleep()
        小白.climb_tree()
        # 小白 is eating
        # 小白 is drinking
        # 小白 is sleeping
        # 小白 is climbing

        小黑 = Dog('小黑')
        小黑.eat()
        小黑.drink()
        小黑.sleep()
        小黑.house_keep()
        # 小黑 is eating
        # 小黑 is drinking
        # 小黑 is sleeping
        # 小黑 is keeping the house
继承: 解决代码的重复

技术图片

技术图片

技术图片

技术图片

    
 1.继承语法:
        class A:
            pass
        class B(A):
            pass
    # B继承A,A是父类,B是子类
    # A是父类 基类 超类
    # B是子类 派生类


 2.子类可以使用父类中的 : 方法 和 静态变量

        class Animal:
            def __init__(self,name):
                self.name = name
            def eat(self):
                print(f'self.name is eating ')
            def drink(self):
                print(f'self.name is drinking ')
            def sleep(self):
                print(f'self.name is sleeping ')

        class Cat(Animal):
            def climb_tree(self):
                print(f'self.name is climbing ')

        class Dog(Animal):
            def house_keep(self):
                print(f'self.name is keeping the house ')

        小白 = Cat('小白')
            # 类名 + ( )
            # 先开辟空间,空间里有一个类指针-->指向Cat
            # 调用init方法,对象在自己的空间中找init没找到就去Cat类中找,init中也没找到,去找父类Animal中的init

            # class AA:pass 没有init ,并且不会报错,是因为默认继承object,object中能找到init
            # 所有在python3当中的类都是继承object类的,object中有init,所有的类都默认的继承object

        小白.eat()
        小白.drink()
        小白.sleep()
        小白.climb_tree()
        # 小白 is eating
        # 小白 is drinking
        # 小白 is sleeping
        # 小白 is climbing

        小黑 = Dog('小黑')
        小黑.eat()
        小黑.drink()
        小黑.sleep()
        小黑.house_keep()
        # 小黑 is eating
        # 小黑 is drinking
        # 小黑 is sleeping
        # 小黑 is keeping the house
        
        
        
 3.当子类和父类的方法重名的时候,我们只使用子类的方法,而不会去调用父类的方法。
  子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。
        class Animal:
            def __init__(self,name):
                self.name = name
            def eat(self):
                print(f'self.name is eating ')
            def drink(self):
                print(f'self.name is drinking ')
            def sleep(self):
                print(f'self.name is sleeping ')

        class Cat(Animal):
            def eat(self):
                print(f'self.name is eating ')
            def climb_tree(self):
                print(f'self.name is climbing ')

        小白 = Cat('小白')
        小白.eat()
        # 小白 is eating
        
 4.子类想要调用父类的方法的同时还想执行自己的同名方法,在子类的方法中调用父类的方法 :父类名.方法名(self)
        # 比如:猫和狗在调用eat的时候既调用自己的也调用父类的
        class Animal:
            def __init__(self,name,food):
                self.name = name
                self.food = food
                self.blood = 100   #血条
                self.wisdom = 100  #智慧
            def eat(self):
                print(f'self.name is eating self.food')
            def drink(self):
                print(f'self.name is drinking ')
            def sleep(self):
                print(f'self.name is sleeping ')

        class Cat(Animal):
            def eat(self):
                self.blood += 100  #吃了东西后血条+100
                Animal.eat(self)  #在子类的方法中调用父类的方法 :父类名.方法名(self)  手动添加self,把self传进去。类名调用方法名时不会自动传对象
            def climb_tree(self):
                print(f'self.name is climbing ')
                self.drink()    #爬树的过程中喝水  当自己没有喝水的方法时,直接调用父类的方法


        class Dog(Animal):
            def eat(self):
                self.wisdom += 100  #吃了东西后智慧+100
                Animal.eat(self)
            def house_keep(self):
                print(f'self.name is keeping the house ')

        小白 = Cat('小白','猫粮')
        小黑 = Dog('小黑','狗粮')
        小白.eat()
        小黑.eat()
        print(小白.__dict__)
        print(小黑.__dict__)
        # 小白 is eating 猫粮
        # 小黑 is eating 狗粮
        # 'name': '小白', 'food': '猫粮', 'blood': 200, 'wisdom': 100  #吃了东西后血条+100
        # 'name': '小黑', 'food': '狗粮', 'blood': 100, 'wisdom': 200  #吃了东西后智慧+100

小结:

 继承语法 class 子类名(父类名):pass
 父类和子类方法的选择:
         1.子类的对象,如果去调用方法,永远优先调用自己的
         2.如果自己有 ,用自己的
         3.自己没有 ,用父类的
         4.如果自己有 还想用父类的 : 直接在子类方法中调父类的方法 父类名.方法名(self)
                
                
   # 思考一:下面代码的输出?
        class Foo:
            def __init__(self):
                self.func()   # 在每一个self调用func的时候,我们不看这句话是在哪里执行,只看self是谁

            def func(self):
                print('in foo')

        class Son(Foo):
            def func(self):
                print('in son')

        Son()#in son

# 思考二: 如果想给狗和猫定制个性的属性
# 猫 : eye_color眼睛的颜色
# 狗 : size型号
        class Animal:
            def __init__(self, name,food):
                self.name = name
                self.food = food
                self.blood = 100
                self.wisdom = 100
            def eat(self):
                print('%s is eating %s'%(self.name,self.food))
            def drink(self):
                print('%s is drinkig'% self.name)
            def sleep(self):
                print('%s is sleeping'% self.name)

        class Cat(Animal):
            def __init__(self,name,food,eye_color):
                Animal.__init__(self,name,food)   # 调用了父类的初始化,去完成一些通用属性的初始化
                self.eye_color = eye_color        # 派生属性

        class Dog(Animal):
            def __init__(self, name, food, size):
                Animal.__init__(self, name, food)
                self.size = size
        小白 = Cat('小白','猫粮','蓝色')
        print(小白.__dict__)#'name': '小白', 'food': '猫粮', 'blood': 100, 'waise': 100, 'eye_color': '蓝色'
        小黑 = Dog('小黑','狗粮','big')
        print(小黑.__dict__)#'name': '小黑', 'food': '狗粮', 'blood': 100, 'waise': 100, 'size': 'big'
单继承:
    # 调子类的 : 子类自己有的时候,调子类的
    # 调父类的 : 子类自己没有的时候,就调父类的
    # 调子类和父类的 :子类父类都有,在子类中调用父类的
    
    #单继承:
    class D:
        def func(self):
            print('in D')
    class C(D):
        def func(self):
            print('in C')
    class B(C):
        def func(self):
            print('in B')
    class A(B):
        def func(self):
            print('in A')

    A().func()  # a = A() ---> a.func()
    # in A
多继承:
# 多继承 有好几个爹
     有一些语言不支持多继承 java
    
     python语言的特点 : 可以在面向对象中支持多继承
            
     一个类有多个父类,在调用父类方法的时候,按照继承顺序,先继承的哪个,就先去哪个寻找

        class A:
            def func(self):print('in A')
        class B:
            def func(self):print('in B')

        class C(A,B):pass
        C().func()#in A

        class C(B,A):pass
        C().func()# in B
知识点补充:
    1.object 类:    
    
         object类 是 类祖宗, 所有在python3当中的类都是继承object类的, object中有init,所有的类都默认的继承object。


            class A:
                pass
            a = A()
        
        写成:
        
             class A(object):
                pass
             a = A()
                
                
  2.__bases__   如果没有指定基类,python的类会默认继承object类,object是所有python类的基类。 
         class A:pass
         print(A.__bases__)#(<class 'object'>,)
         class C:pass
         print(C.__bases__)#(<class 'object'>,)
         class B(A,C):pass
         print(B.__bases__)#(<class '__main__.A'>, <class '__main__.C'>) #只显示所有父类,不显示爷爷类


3.isinstance 和 type

     ## isinstance  
        isinstance(obj,cls)检查是否obj是否是类 cls 的对象
        
          a = 1
          b = 'abc'
          print(isinstance(a,int))#True
          print(isinstance(a,float))#False
          print(isinstance(b,str))#True

      ## type
          a = 1
          b = 'abc'
          print(type(a) is int)#True
          print(type(b) is str)#True
    
      #
           class Cat:
               pass
           小白 = Cat()
           print(type(小白) is Cat)#True
           print(isinstance(小白,Cat))#True

      #
         class Animal:pass
         class Cat(Animal):pass
         小白 = Cat()

         print(type(小白) is Cat)#True
         print(type(小白) is Animal)#False

         print(isinstance(小白,Cat))#True   判断对象是不是类的对象
         print(isinstance(小白,Animal))#True  判断对象是不是子类的对象

4.绑定方法和普通的函数:
        from types import FunctionType,MethodType
        # FunctionType : 函数
        # MethodType : 方法

        #【面试】
        方法和函数的区别不在于是否写在类里边,而在于谁调用它,和函数写在哪里无关:
            用类名调用类的函数就是函数
            用对象调用类的函数就是方法
        
        class A:
            def func(self):
                print('in func')

        print(A.func)#函数 <function A.func at 0x000002610CE79400>
        print(isinstance(A.func,FunctionType))#True
        print(isinstance(A.func,MethodType))#False

        a = A()
        print(a.func)#方法  <bound method A.func of <__main__.A object at 0x000002610CD07DD8>>
        print(isinstance(a.func,MethodType))#True
        print(isinstance(a.func,FunctionType))#False


5.其他:

        class A:
            role = '法师'
            def func1(self):pass
            def func2(self):pass

        class B:pass

        class C(B,A):pass
        
        【1】 类名.__base__# 类的第一个父类
        print(A.__base__)#<class 'object'>
        print(C.__base__)#<class '__main__.B'>
        
        
        【2】 类名.__bases__# 类所有父类构成的元组
        print(C.__bases__)#(<class '__main__.B'>, <class '__main__.A'>)

        
        【3】我们定义的类的属性有两种方式查看:
            dir(类名):查出的是一个名字列表
            
            #类的字典属性   
            类名.__dict__:查出的是一个字典,key为属性名,value为属性值
              
        print(A.__dict__)#'__module__': '__main__', 'role': '法师', 'func1': <function A.func1 at 0x0000026EA0B68AE8>, 'func2': <function A.func2 at 0x0000026EA0B68B70>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None
        
        
        【4】 类名.__name__# 类的名字(字符串)   函数名也可通过此方式查看
        print(A.__name__)#A

        
        【5】 类名.__class__    实例对应的类(仅新式类中)   自定义类默认为type类型
        print(A.__class__)#<class 'type'>
        print(B.__class__)#<class 'type'>
        print(C.__class__)#<class 'type'>

        
       【6】  类名.__module__# 类定义所在的模块
            print(C.__module__)# __main__

            #如果下面这句话在 module.py模块中
            print(C.__module__)#__main__
            # 导入module模块
            import module
            # 结果: module

            
        【7】  __doc__  查看函数或类的注释
        #项目中要给类和函数添加注释

            def func():
                '''
                这个函数主要是用来卖萌
                '''
                pass

            print(func.__doc__)#  这个函数主要是用来卖萌

            class Cat:
                '''
                这个类是用来描述游戏中的猫咪角色
                '''
                pass
            print(Cat.__doc__)#  这个类是用来描述游戏中的猫咪角色


 6.使用pickle存取自定义类的对象的方式
        #前提:必须有类
        #通过pickle 存储和读取对象
        class Course:
            def __init__(self,name,period,price):
                self.name = name
                self.period = period
                self.price = price

        python = Course('python','6 moneth',21800)
        linux = Course('linux','5 moneth',19800)
        go = Course('go','4 moneth',12800)

        import  pickle
        with open('pickle_file','ab') as f:
            pickle.dump(python,f)
            pickle.dump(linux,f)
            pickle.dump(go,f)

        with open('pickle_file','rb') as f:
            while True:
                try:
                    obj = pickle.load(f)
                    print(obj.name,obj.period,obj.price)
                except EOFError:
                    break
        # python 6 moneth 21800
        # linux 5 moneth 19800
        # go 4 moneth 12800

以上是关于面向对象:继承,知识点补充的主要内容,如果未能解决你的问题,请参考以下文章

Java学习记录(补充三:面向对象的封装和继承)

面向对象知识点

python全栈开发第十六篇面向对象三大特性——多台和继承补充

[C++] 面向对象语言的三大特性--继承

[C++] 面向对象语言的三大特性--继承

JS面向对象——Object对象的方法补充原型继承关系图