day20总结

继承

# 父类
class ParentClass1:
    pass


class ParentClass2:
    pass


# 子类
class SubClass1(ParentClass1):
    pass


# 继承多个父类
class SubClass2(ParentClass1, ParentClass2):
    pass


# 查看继承的父类: __bases__,是类的属性,用来查找当前类的父类.
print(SubClass1.__bases__)  # (<class '__main__.ParentClass1'>,)
print(SubClass2.__bases__)  # (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

如何选择继承关系

如何寻找继承关系:
要想寻找继承关系,首先要 "先抽象,再继承".

什么是抽象?
抽象指的是抽取相似的部分,称之为抽象.

  • 先抽象(抽象思想):
    奥巴马 ---> 人类 ---> 动物类
    麦兜 ---> 猪类 ---> 动物类
    小丁丁 ---> 狗类 ---> 动物类

    抽象定义动物类,称之为父类.
    特征:
    眼睛,鼻子...
    技能:
    吃,喝,撒...

  • 再继承(在程序中):
    奥马巴对象 ---> 调用人类 ---> 继承动物类
    麦兜对象 ---> 调用猪类 ---> 继承动物类
    小丁丁对象 ---> 调用狗类 ---> 继承动物类

继承的关系:
对象是特征与技能的结合体.
类是一系列对象相同的特征与技能的结合体.
继承是一系列类相同的特征与技能的结合体.

# 不继承情况下:
# # 老师类: 名字,年龄,性别
# class OldboyTeacher:
#     school = 'oldboy'
#
#     def __init__(self, name, age, sex):
#         self.name = name
#         self.age = age
#         self.sex = sex
#
#     # 老师修改分数技能
#     def change_score(self):
#         print(f'老师[{self.name} 修改分数...]')
#
#
# # 学生类:  名字,年龄,性别
# class OldboyStudent:
#     school = 'oldboy'
#
#     def __init__(self, name, age, sex):
#         self.name = name
#         self.age = age
#         self.sex = sex
#
#     # 学生可以选择课程
#     def choose_course(self, course):
#         print(f'学生[{self.name}]选择课程[{course}]')


# 父类:
'''
抽象:
    school
    __init__(self, name, age, sex)
'''
class OldboyPeople:
    school = 'oldboy'

    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

# 老师类: 名字,年龄,性别
class OldboyTeacher(OldboyPeople):
    # 老师修改分数技能
    def change_score(self):
        print(f'老师[{self.name} 修改分数...]')

# 学生类:  名字,年龄,性别
class OldboyStudent(OldboyPeople):

    # 学生可以选择课程
    def choose_course(self, course):
        print(f'学生[{self.name}]选择课程[{course}]')

stu1 = OldboyStudent('小丁丁', 95, 'female')
tea1 = OldboyTeacher('tank', 17, 'male')

print(stu1.name, stu1.age, stu1.sex)
print(tea1.name, tea1.age, tea1.sex)

继承背景下属性查找顺序

在继承背景下,对象属性的查找顺序:
1.对象查找属性会先从对象的名称空间中查找.
2.若对象没有,则会去类里面找.
3.若当前类是子类,并且没有对象找的属性,会去父类中查找

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

# # 父类
# class OldboyPeople:
#     school = 'oldboy'
#
#     def __init__(self, name, age, sex):
#         self.name = name
#         self.age = age
#         self.sex = sex
#
#
# # 子类
# class OldboyTeacher(OldboyPeople):
#
#     # 老师修改分数技能
#     def change_score(self):
#         print(f'老师[{self.name} 修改分数...]')
#
#
# tea1 = OldboyTeacher('tank', 17, 'male')
# print(tea1.school)

# 查看对象名称空间
# print(tea1.__dict__)
# __class__: 对象的属性,查看当前对象的类.
# 查看子类名称空间
# print(tea1.__class__.__dict__)
# 查看父类名称空间
# print(tea1.__class__.__bases__[0].__dict__)


# 验证对象属性的查找顺序
class Foo:

    def f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.f1()


class Soo(Foo):
    def f1(self):
        print('Soo.f1')


soo_obj = Soo()
soo_obj.f2()
'''
Foo.f2
Soo.f1
'''

派生

什么是派生?
派生指的是子类继承父类的属性,并且派生出新的属性.(*****)

子类派生出新的属性,若与父类的属性相同,则以子类的为准.
继承是谁与谁的关系, 指的是类与类的关系,子类与父类是从属关系.

# 验证对象属性的查找顺序
class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.f1()


class Soo(Foo):
    def f1(self):
        print('Soo.f1')


soo_obj = Soo()
soo_obj.f1()  # Soo.f1

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

 class OldboyPeople:
#     def __init__(self, name, age, sex):
#         self.name = name
#         self.age = age
#         self.sex = sex
#
#
# class OldboyTeacher(OldboyPeople):
#     # 等级, 薪资
#     def __init__(self, name, age, sex, level, sal):
#         self.name = name
#         self.age = age
#         self.sex = sex
#         self.level = level
#         self.sal = sal
#
#
# class OldboyStudent(OldboyPeople):
#     # 课程
#     def __init__(self,name, age, sex, course):
#         self.name = name
#         self.age = age
#         self.sex = sex
#         self.course = course


# 问题: 子类继承父类的__init__毫无意义.
# 解决:
'''
解决方式有两种:
    方式一:
        直接通过 父类.(调用)__init__,把__init__当做普通函数使用,传入对象与继承的属性.
        
    方式二:
        super是一个特殊的类,在子类中调用super()会得到一个特殊的对象,
        通过"."指向的是父类的名称空间.

    注意: 两种方式不要混合使用.
'''

class OldboyPeople:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex


# 方式一:
# class OldboyTeacher(OldboyPeople):
#     # 等级, 薪资
#     def __init__(self, name, age, sex, level, sal):
#         OldboyPeople.__init__(self, name, age, sex)
#         self.level = level
#         self.sal = sal
#
#
# class OldboyStudent(OldboyPeople):
#     # 课程
#     def __init__(self, name, age, sex, course):
#         OldboyPeople.__init__(self, name, age, sex)
#         self.course = course
#
#     def choose_course(self):
#         print(f'学生{self.name}选择课程{self.course}')


# 方式二:
class OldboyTeacher(OldboyPeople):
    # 等级, 薪资
    def __init__(self, name, age, sex, level, sal):
        super().__init__(name, age, sex)
        self.level = level
        self.sal = sal


class OldboyStudent(OldboyPeople):
    # 课程
    def __init__(self, name, age, sex, course):
        super().__init__(name, age, sex)
        self.course = course

    def choose_course(self):
        print(f'学生{self.name}选择课程{self.course}')


# print(super)
tea1 = OldboyTeacher('tank', 17, 'male', 9, '3.0')
stu1 = OldboyStudent('小健健', 20, 'female', 'python')
print(tea1.name, tea1.level)
print(stu1.name, stu1.course)
stu1.choose_course()

新式类与经典类

新式类与经典类(了解):
在python2中,才会有新式类与经典类之分.
在python3中,所有的类都是新式类.

新式类:
继承object的类都称之为新式类.
python3中,子类不继承自定义的类,默认继承object.

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

# 在python3:
# 新式类:
# class Foo(object):
#     pass
#
# class Goo(Foo):
#     pass
#
# # print(Foo.__bases__)  # (<class 'object'>,)
# print(Goo.__bases__)  # (<class 'object'>,)


# python2:

'''
mro(): 属于object--> type的函数, 用来查看当前类的继承顺序, 在多继承的情况下.
'''
class A:
    # x = 2
    pass
class B:
    # x = 3
    pass
# 多继承情况下:
class C(A, B):
    # print('C...')
    # x = 1
    pass


# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
print(object)
print(C.mro())

钻石继承

钻石继承也可以称之为菱形继承.(了解)

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

  • 经典类:
    深度优先:

  • 新式类:
    广度优先:

# 验证
class A:
    # def test(self):
    #     print('from A')
    pass

class B(A):
    # def test(self):
    #     print('from B')
    pass

class C(A):
    def test(self):
        print('from C')
    pass

class D(B):
    # def test(self):
    #     print('from D')
    pass

class E(C):
    # def test(self):
    #     print('from E')
    pass

class F(D,E):
    # def test(self):
    #     print('from F')
    pass


# 新式类: F-D-B-E-C-A-object
f1 = F()
f1.test()

# 经典类: F-D-B-A-E-C

通过继承实现修改json模块数据类型

import json
from datetime import date, datetime

print(json.JSONEncoder)
print(datetime.today())  # 当前时间
print(date.today())  # 当前日期

# 开发者的角度: 直接转成str
# dict1 = {
#     'name': 'tank',
#     'today': str(datetime.today()),
#     'today2': str(date.today())
# }
#
# res = json.dumps(dict1)
# print(res)


# isinstance:
# python内置的函数,可以传两个参数,判断参数一是否式参数二的一个实例.

# 开源者的角度: 修改json源码
class MyJson(json.JSONEncoder):
    def default(self, o):

        # 子类派生的功能
        # 判断o是否式datetime的一个实例
        if isinstance(o, datetime):
            return o.strftime('%Y-%m-%d %X')
        elif isinstance(o, date):
            return o.strftime('%Y-%m-%d')
        else:
            # 继承父类的default方法的功能
            return super().default(self, o)


dict1 = {
    'name': 'tank',
    'today': datetime.today(),
    'today2': date.today()
}

res = json.dumps(dict1, cls=MyJson)  # cls=None,默认指向的是原json的JSONEncoder
print(res)

课堂笔记

面向对象阶段最重要的知识点:
    面向对象的三大特性:
        1.继承  (组合)
        2.封装
        3.多态


继承:
(夺命三问)
1.什么是继承?
    继承指的是新建类的方法, 新建的类称之为子类或者派生类,
    子类继承的类叫做父类,也称之为基类或超类.

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

    ******
    注意: 在python中,一个子类可以继承多个父类,其他语言只能一个子类继承一个父类.

2.为什么要继承?
    继承的目的是为了减少代码冗余(减少重复代码).

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

    class 父:
        xxx = 111
        pass

    class 子(父):
        pass
posted @ 2019-10-10 14:49  lucky_陈  阅读(76)  评论(0编辑  收藏  举报