zoukankan      html  css  js  c++  java
  • 1010 笔记

    面向对象之继承

    面向对象的三大特性:

    1. 继承 (组合)
    2. 封装
    3. 多态

    一.什么是继承

    继承指的是新建类的方式,新建的类称之为子类或者派生类

    子类继承的类叫做父类,也称之为基类或超类.

    继承的特征:

    子类可以继承父类的属性(特征与技能),子类可以派生出自己的属性(特征与技能)

    注意:在python中一个子类可以继承多个父类

    二.为什么要继承

    继承的目的是为了减少代码的冗余(减少重复代码)

    三.如何实现继承

    1. 首先要确定好谁是子类,谁是父类
    2. 在定义时,子类名 + ( ),()内写父类,实现继承

    1.__bases__查看类的父类

    __bases__是类的属性,用来查看当前类的父类

    class fu:
    	pass
    class zi(fu):
        pass
    print(zi.__bases__)
    #  (<class '__main__.fu'>,)
    #  子类可以继承多个父类
    class ye:
    	pass
    class sun(fu,ye):
        pass
    print(sun.__bases__)
    # (<class '__main__.fu'>, <class '__main__.ye'>)
    

    2.寻找继承关系

    想要寻找继承关系,就要'先抽象,再继承'

    什么是抽象

    抽象指的是抽取相似的部分,称之为抽象

    也就是获得对象对应的相似的将之聚合为一类.

    类似于人狗猪同属于哺乳动物类,爬行动物与哺乳动物同属于动物类

    继承的关系

    对象是特征与继承的结合体

    类是一系列对象相同的特征与技能的结合体

    继承是一系列类相同特征与技能的结合体

    # 老师类
    class teacher:
        school = 'oldboy'
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def change(self):
            print(f'老师{self.name}更改分数')
    
    # 学生类
    class student:
        school = 'oldboy'
        def __init__(self,name,age):
            self.name =name
            self.age = age
        def choise(self):
            print(f'用户{self.name}可以选课')
    
    t1 = teacher('数学',55)
    s1 = student('aaa',18)
    
    '''使用继承思想减少重复代码'''
    '''使用继承方法'''
    # 老男孩的老师学生基类
    class OldPeople:
        school = 'oldboy'
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    class teacher(OldPeople):
        def change(self):
            print(f'老师{self.name}更改分数')
    
    class student(OldPeople):
        def choise(self):
            print(f'用户{self.name}可以选课')
    
    t1 = teacher('数学',55)
    s1 = student('aaa',18)
    print(t1.school,t1.age)     # oldboy 55
    print(s1.school,s1.name)    # oldboy aaa
    
    

    3.对象属性的查找顺序

    对象==> 子类 ==> 父类 ==> object(基类)

    在继承背景下,对象属性的查找顺序:

    ​ 1.对象查找属性会先从对象的名称空间中查找

    ​ 2.若对象没有,则会去类里面找

    ​ 3.若当前类是子类,且没有对象找的属性,会去父类中查找

    注意:对象查找属性,若子类有,不管父类有没有,以子类为准

    .__dict__查看对象的名称空间

    .__class__对象的属性,查看当前对象的类

    验证对象属性的查找顺序

    class foo:
        def f1 (self):
            print('foo.f1')
    
        def f2(self):
            print('f00.f2')
            self.f1()
    
    class soo(foo):
        def f1(self):
            print('s00.f1')
    
    s = soo()
    s.f2()
    # f00.f2
    # s00.f1
    

    4.派生

    什么是派生:

    派生指的是子类继承父类的属性,并且可以派生出新的属性

    子类派生出新的属性,若与父类的属性相同,以子类为准

    继承是谁与谁的关系,指的是类与类的关系,子类与父类是从属关系

    5.重用父类

    子类派生新的属性,并重用父类的属性

    '''学生与老师的信息表有相同的姓名,年龄还有不同的等级(老师)与成绩(学生),如果想要使用继承解决代冗余问题'''
    '''使用继承方法'''
    # 老师类
    class teacher:
        school = 'oldboy'
        def __init__(self,name,age,level):
            self.name = name
            self.age = age
            self.level = level  # 老师有等级
        def change(self):
            print(f'老师{self.name}更改分数')
    
    # 学生类
    class student:
        school = 'oldboy'
        def __init__(self,name,age,grade):
            self.name =name
            self.age = age
            self.grade = grade  # 学生有成绩
        def choise(self):
            print(f'用户{self.name}可以选课')
    
    t1 = teacher('数学',55,100)
    s1 = student('aaa',18,'A')
    
    

    方式一:直接通过调用父类.__init____init__当做普通函数使用,传入对象,与继承的属性.

    '''重用'''
    # 老男孩的老师学生基类
    class OldPeople:
        school = 'oldboy'
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    # 老师类
    class teacher(OldPeople):
        def __init__(self,name,age,level):
            #  定义的所有需要的变量
            OldPeople.__init__(self,name,age)
            #  将父类中需要的参数调用到子类中
            self.level = level
        def change(self):
            print(f'老师{self.name}更改分数')
    
    class student(OldPeople):
        def __init__(self,name,age,grade):
            OldPeople.__init__(self,name,age)
            self.grade = grade
        def choise(self):
            print(f'用户{self.name}可以选课')
    
    t1 = teacher('数学',55,100)
    s1 = student('aaa',18,'A')
    print(t1.school,t1.age,t1.level)     # oldboy 55 100
    print(s1.school,s1.name,s1.grade)    # oldboy aaa A
    

    super的使用

    方式二: 使用特殊类super(),在子类调用super()会得到一个特殊的对象,而这对象指向的是父类的名称空间,拿到__init__

    '''重用'''
    # 老男孩的老师学生基类
    class OldPeople:
        school = 'oldboy'
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    # 老师类
    class teacher(OldPeople):
        def __init__(self,name,age,level):
            #  定义的所有需要的变量
            super().__init__(name,age)
    #  这里super就代表self ,所以使用super,不需要使用self
            self.level = level
        def change(self):
            print(f'老师{self.name}更改分数')
    
    class student(OldPeople):
        def __init__(self,name,age,grade):
            super().__init__(name,age)
            self.grade = grade
        def choise(self):
            print(f'用户{self.name}可以选课')
    
    t1 = teacher('数学',55,100)
    s1 = student('aaa',18,'A')
    print(t1.school,t1.age,t1.level)     # oldboy 55 100
    print(s1.school,s1.name,s1.grade)    # oldboy aaa A
    

    两种方式不要混合使用

    super用法的小结:

    super():
        在单继承中就是单纯的寻找父类
        在多继承中就是根据子节点 所在图 的 mro顺序找寻下一个类
    遇到多继承和super
        对象.方法
            找到这个对象对应的类
            将这个类的所有父类都找到画成一个图
            根据图写出广度优先的顺序
            再看代码,看代码的时候要根据广度优先顺序图来找对应super
    

    6.经典类与新式类

    在python2中,才会有新式类和经典类之分

    在python3中,所有的类都是新式类

    新式类

    继承object的类都称之为新式类

    python3中子类不继承自定义的类,所有的的类默认继承object

    经典类

    在python2中,凡是没有继承object的类都是经典类

    mro()

    python中内置的函数,用来查看当前类的继承顺序,在多继承的情况下

    class a:
        x=3
        pass
    
    class b:
        x = 2
        pass
    
    class c(a,b):
        pass
    
    print(c.x)  # 3
    # 类继承时从左到右查找,从对象到子类到父类最后object
    print(c.mro())
    # [<class '__main__.c'>, <class '__main__.a'>, <class '__main__.b'>, <class 'object'>]
    

    7.钻石继承的查找顺序

    如果子类继承自两个单独的超类,而那两个超类又继承自同一个公共基类,那么就构成了钻石继承体系。这种继承体系很像竖立的菱形,也称作菱形继承。

    ​ 在多继承的情况下形成的钻石继承(继承顺序的不一致)

    经典类: 深度优先

    一条路走到黑,遍历时遵循深度优先

    新式类:广度优先

    不找多个类最后继承的同一个类,直接去找下一个父类,广度优先

    8.修改json数据格式品种

    from datetime import date,datetime
    import json
    '''datetime模块化时间 json是不能序列化的,报错解决'''
    
    # 方式一 开发者角度:使用str强制准换
    
    dic = {
        'name':'tank',
        'today':str(datetime.today()),
        'today2':str(date.today())
    }
    res = json.dumps(dic)
    print(res)
    
    
    # 方式二 开源者角度:修改json源码
    class MyJson(json.JSONEncoder):
        # 继承父类的属性,派生出自己的属性,继承json.JSONEncoder的属性
        # 继承的是可序列化的数据类型
        def default(self, o):
        # default 方法可以return 出去可序列化的类型,覆盖父类的default
            if isinstance(o,datetime):
    # python内置的函数,可以传入两个参数,判断参数一是否是参数二的一个实例
    # 传入dic 字典,字典的每一个属性就会传入到o中,然后判断o是否datetime的一个实例
                return o.strftime('%Y-%m-%d %X')
            # strftime() 函数接收以时间元组,并返回以可读字符串表示的当地时间
            elif isinstance(o,date):
            # 继续判断o是否是data的一个实例
                return o.strftime('%Y-%m-%d')
    
            else:
            # 如果不是以上两个类的,就使用父类的方法
                return super().default(self,o)
                # super()指向的是父类,这里使用父类的default方法
    
    
    dic = {
        'name':'tank',
        'today':datetime.today(),
        'today2':date.today()
    }
    
    res = json.dumps(dic,cls=MyJson )
    # cls 默认指向原json类中JSONEncoder,现在将其指向自己写的MyJson类中
    print(res)
    # {"name": "tank", "today": "2019-10-10 17:58:44", "today2": "2019-10-10"}
    
    
  • 相关阅读:
    c++ 网络编程(四) LINUX/windows下 socket 基于I/O复用的服务器端代码 解决多进程服务端创建进程资源浪费问题
    c++ 网络编程(三) LINUX/windows 进程间的通信原理与实现代码 基于多进程的服务端实现
    c++ 网络编程(二) linux 下多进程socket通信 多个客户端与单个服务端交互代码实现回声服务器
    c++ 网络编程(一)TCP/UDP windows/linux 下入门级socket通信 客户端与服务端交互代码
    c++ MFC图像处理CImage类常用操作代码
    vue 模板语法
    占位1
    MongoDB
    Node.js fs-文件系统
    nodeJs 常用模块(一)
  • 原文地址:https://www.cnblogs.com/fwzzz/p/11649751.html
Copyright © 2011-2022 走看看