zoukankan      html  css  js  c++  java
  • 面向对象之继承

    一.继承

    1.什么是继承

      在程序中继承是一种新建子类的方式,新创建的类称之为子类派生类,被继承的类称之为父类基类超类

      继承描述的一种遗传关系,子类可以重用父类的属性

    2.为何用继承?

      减少类与类之间代码冗余的问题

    3.如何继承

      先抽象再继承

    在Python中继承的特点?单继承&多继承

    class Parent1(object):

      pass

    class Parent2:

      pass

    class Sub1(Parent1):

      pass

    class Sub2(Parent2):

      pass

    print(Parent1.__bases__)

    print(Parent2.__bases__)

    python2与python3在继承上的区别

    新式类:但凡继承object类的子类,以及该子类的子子类,...都称之为新式类

    经典类:没有继承object类的子类,以及该子类的子子类,...都称之为经典类

    只有在Python2中才区分新式类与经典类

    二.基于继承解决类与类代码冗余问题

    在子类派生的新功能中如何重用父类的功能:

    方式一:指名道姓地访问某一个类中的函数,与继承无关

    class OldboyPeople:
        school = 'Oldboy'
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    print(OldboyPeople.__init__)
    
    class OldboyPeople(OldboyPeople):
        
        def choose_course(self):
            print('%s is choosing course'%self.name)
    
    class OldboyTeacher(OldboyPeople):
        #            tea, 'egon', 18, 'male', 10, 3000
        def __init__(self, name, age, gender,level,salary):
            # self.name = name
            # self.age = age
            # self.gender = gender
            OldboyPeople.__init__(self, name, age, gender)
    
            self.level=level
            self.salary=salary
    
        def score(self,stu,num):
            stu.num=num
            print('老师%s给学生%s打分%s' %(self.name,stu.name,num))
    
    # stu=OldboyStudent('kevin',38,'male') #__init___(stu1,'kevin',38,'male')
    # print(stu.__dict__)
    tea=OldboyTeacher('egon',18,'male',10,3000) #__init___(tea,'egon',18,'male',10,3000)
    print(tea.__dict__)
    # print(stu.school)
    # print(tea.school)

    三. 在单继承背景下属性的查找

    在单继承背景下,无论是新式类还是经典类属性查找顺序都一样

    先obj->父类->...

    class Foo:
        def f1(self):
            print('Foo.f1')
            
        def f2(self):
            print('Foo.f2')
            self.f1() #obj.f1()
    
    class Bar(Foo): 
        def f1(self):
            print('Bar.f1')
    obj=Bar()
    obj.f2()
    
    在多继承背景下,如果一个子类继承了多个分支,但是多个分支没有汇聚到一个非常object类,无论是新式类还是经典类查找顺序都一样,会按照从左到右的顺序一个分支一个分支的查找下去

    在多个继承背景下,如果一个子类继承了多个分支,但是多个分支最终汇聚到一个非object类(菱形继承问题)

    新式类:广度优先查找:obj->A->B->E->C->F->D->G->object

    经典类:深度优先查找:obj->A->B->E->G->C->F->D

    四.super方法

    在子类派生出的新功能中如何重用父类的功能:

    方式一:指名道姓访问某一个类中的函数,与继承无关

    方式二:super(OldboyTeacher,self),在python3中super可以不停传参,调用该函数会得到一个特殊的对象,该对象是专门用来访问父类中属性,

      强调:super会严格参照类的mro列表依次查找属性

    #A没有继承B,
    class A:
        def test(self):
            print('A.test')
            super().test()
    class B:
        def test(self):
            print('from B')
    class C(A,B):
        pass
    
    c=C()
    c.test()
    print(C.mro())

     作业:

    1、类的属性和对象的属性有什么区别?

    类的属性是类里的对象共有的,对象的属性是对象特有的.
    2、面向过程编程与面向对象编程的区别与应用场景?

    面向过程可以把复杂的问题拆分,简单化流程化,适用于扩展性要求低的应用场景,如登录界面,面向对象编程,适用于对拓展性要求高的场景,如对战游戏.
    3、类和对象在内存中是如何保存的。

    类是直接执行代码,将产生的名称存入名称空间,  对象是先产生一个空的对象 然后运行__init__函数 将这个对象以及额外的参数组装后传给该函数,
    4、什么是绑定到对象的方法,、如何定义,如何调用,给谁用?有什么特性

    类中的功能函数,就是该类中对象的绑定方法,

    class 类名:

      def 函数名(self):

        pass

    p2.函数名()

    给对象用

    特殊:在使用绑定方法时,不需要关系self参数 会自动将这个对象本身传进来

    对象用绑定方法是 最后执行的还是类中的那个函数

    5、如下示例, 请用面向对象的形式优化以下代码
    在没有学习类这个概念时,数据与功能是分离的,如下
    def exc1(host,port,db,charset):
      conn=connect(host,port,db,charset)
      conn.execute(sql)
      return xxx

    def exc2(host,port,db,charset,proc_name)
      conn=connect(host,port,db,charset)
      conn.call_proc(sql)
      return xxx
    # 每次调用都需要重复传入一堆参数
    exc1('127.0.0.1',3306,'db1','utf8','select * from tb1;')
    exc2('127.0.0.1',3306,'db1','utf8','存储过程的名字')

    class MySQLHandler:
        def __init__(self,host,port,db,charset='utf8'):
            self.host=host
            self.port=port
            self.db=db
            self.charset=charset
            self.conn=connect(self.host,self.port,self.db,self.charset)
        def exc1(self,sql):
            return self.conn.execute(sql)
    
        def exc2(self,sql):
            return self.conn.call_proc(sql)
    
    
    obj=MySQLHandler('127.0.0.1',3306,'db1')
    obj.exc1('select * from tb1;')
    obj.exc2('存储过程的名字')

    6、下面这段代码的输出结果将是什么?请解释。
    class Parent(object):
      x = 1

    class Child1(Parent):
      pass

    class Child2(Parent):
      pass

    print(Parent.x, Child1.x, Child2.x)
    Child1.x = 2
    print(Parent.x, Child1.x, Child2.x)
    Parent.x = 3
    print(Parent.x, Child1.x, Child2.x)

    1,1,1

    1,2,1

    3,2,3

    7、多重继承的执行顺序,请解答以下输出结果是什么?并解释。

    class A(object):
      def __init__(self):
      print('A')
      super(A, self).__init__()

    class B(object):
      def __init__(self):
      print('B')
      super(B, self).__init__()

    class C(A):
      def __init__(self):
      print('C')
      super(C, self).__init__()

    class D(A):
      def __init__(self):
      print('D')
      super(D, self).__init__()

    class E(B, C):
      def __init__(self):
      print('E')
      super(E, self).__init__()

    class F(C, B, D):
      def __init__(self):
      print('F')
      super(F, self).__init__()

    class G(D, B):
      def __init__(self):
      print('G')
      super(G, self).__init__()

    if __name__ == '__main__':
      g = G()
      f = F()

    G D A B

    F C B D A

    8、什么是新式类,什么是经典类,二者有什么区别?什么是深度优先,什么是广度优先?在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类.

    在python2中,显式地声明继承object的类,以及该类的子类,都是新式类
    在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类
    当继承关系为菱形结构时(即一个子类继承了多个分支,且分支最后汇聚到一个非object类时),查找顺序经典类深度优先,新式类广度优先.
    深度优先:一条路走到黑,按照从左往右一个分支一个分支的找下去,
    广度优先:从左往右,依次运行,当查找到到汇聚的类时,返回上一子类,进入下一个分支进行查找,当汇聚的父类的分支子类全被查找过以后,查找该父类,继续从左往右依次查找.

    9、用面向对象的形式编写一个老师类, 老师有特征:编号、姓名、性别、年龄、等级、工资,老师类中有功能
    1、生成老师唯一编号的功能,可以用hashlib对当前时间加上老师的所有信息进行校验得到一个hash值来作为老师的编号
    def create_id(self):
    pass
    2、获取老师所有信息
    def tell_info(self):
    pass

    3、将老师对象序列化保存到文件里,文件名即老师的编号,提示功能如下
    def save(self):
    with open('老师的编号','wb') as f:
    pickle.dump(self,f)

    4、从文件夹中取出存储老师对象的文件,然后反序列化出老师对象,提示功能如下
    def get_obj_by_id(self,id):
    return pickle.load(open(id,'rb'))

    10、按照定义老师的方式,再定义一个学生类

    11、抽象老师类与学生类得到父类,用继承的方式减少代码冗余


    12、基于面向对象设计一个对战游戏并使用继承优化代码,参考博客
    http://www.cnblogs.com/linhaifeng/articles/7340497.html#_label1

  • 相关阅读:
    TCP/IP Checksum 吐槽
    RHEL安装时加载第三方raid驱动
    RHEL Channel Bonding
    关于case语句中声明变量并初始化的注意事项
    Allocators与Criterion的相同点及区别
    BitSet构造函数的两种特例
    Bitset<>用于unordered container时的默认hash函数
    C++ Stream
    C++Exception知识整理
    C++String知识整理
  • 原文地址:https://www.cnblogs.com/gongcheng-/p/9837727.html
Copyright © 2011-2022 走看看