昨日回顾

类的加载顺序

  • 类内部的代码什么时候执行?

    • 除了方法里面的代码
    • 其余的所有内容都是在执行这个文件的时候就从上到下依次执行的
    • 不需要调用
    • 如果有同名的方法、属性,总是写在后面的会生
class A:
    wahaha = 'adGa'
    def wahaha(self):
        pass
a = A()
print(a.wahaha)   # 就是后加载进来的方法覆盖了之前加载的属性

类和对象的命名空间

  • 类的命名空间 是在定义类的阶段被加载进来的:

    • 静态变量、类变量 —— 直接定义在类中的变量
    • 动态变量、方法 —— 定义在类中的函数
    • 魔术方法、双下方法
      • 内置的方法 :__init__
      • 内置的变量 : __dict__
  • 对象的命名空间 实例化的时候创建出来的
    • 类指针、类对象指针 执行init之前就已经在了
    • 对象的属性 是在执行init以及之后被添加的
class Student:
    '''这里是对学生类的功能描述'''
    print('123')
print(Student.__dict__)
print(Student.__doc__)
print(Student.__class__)

a = 3
b = 2
def fun():
    a = 4
    def inner():pass

class A:
    a = 1
    def func(self):
        pass

print(a)
print(A.a)

class A:  # parameters形参   arguments实参
    pass
a = A()
#init这个东西你在定义一个类的时候
#假如没有什么属性是你想添加给对象的,你也可以不写init
  • 组合

    • 一个类的对象作为另一个类对象的属性
  • 两个类
    • 人和武器
    • 学生和课程
    • 圆环和圆
class Student:
   def __init__(self,name,age,course):
       self.name = name
       self.age = age
       self.course = course   # self.course = python

class Course:
   def __init__(self,name,price,period):
       self.name = name
       self.price = price
       self.period = period

python = Course('python',20000,'6 months')  # python是一个课程对象
print(python.name)
ju = Student('菊哥',30,python)
#一个类的属性 是一个对象
Student类的course属性 是python对象
#学生的课程属性 和 python对象组合了
#可以通过学生 找到python 可以通过python找到python课程的名字、价格、周期

self.course = python
self.course.name = python.name

print(ju.course.name)
print(ju.course.price)

扩展

ju.name   # 字符串
ju.name.strip()
ju是Student类的对象
ju.name是一个字符串 是str的一个对象
Student类 和 str类 组合

ju.age
ju是Student类的对象
ju.age是int的一个对象
Student类 和 int类 组合

今日内容

  • 面向对象三大特性

    1. 继承 *****
    2. 多态 *
    3. 封装 *****
  • 继承 *****
    • 单继承 可以有效的帮我们提高代码的重用性

      1. 我们写代码的时候
    • 多继承
      1. 规范复杂的功能与功能之间的关系
      2. 工作原理能够帮助你去看源码
      3. 面试重点

单继承

class A(类的名字B):
    pass

##A就变成了B的儿子
# B是 父类、基类、超类
# A是 子类、派生类

class Parent:
    pass

class Son(Parent):
    pass

print(Son.__bases__)

##多继承
class Parent1:
    pass
class Parent2:
    pass

class Son(Parent1,Parent2):
    pass

print(Son.__bases__)

为什么要继承

  • 两个类

    1. 猫 :

      • 属性 :名字,品种,眼睛的颜色
      • 动作 :吃、喝、爬树、抓老鼠
      • 属性:名字,品种
      • 动作 :吃、喝、抓老鼠、拆家
class Cat(object):
    def __init__(self,name,kind,eyes_color):
        self.name = name
        self.kind = kind
        self.eyes_color = eyes_color

    def eat(self,food):
        print('%s eat %s'%(self.name,food))

    def drink(self):
        print('%s drink water'%(self.name))

    def climb(self):
        print('%s climb tree'%(self.name))

    def catch(self):
        print('%s catch mouse'%(self.name))

class Dog(object):
    def __init__(self,name,kind):
        self.name = name
        self.kind = kind

    def eat(self,food):
        print('%s eat %s'%(self.name,food))

    def drink(self):
        print('%s drink water'%(self.name))

    def catch(self):
        print('%s catch mouse'%(self.name))

    def chai(self):
        print('%s cha'%(self.name))

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

    def eat(self,food):
        print('%s eat %s'%(self.name,food))

class Cat(Animal):pass
class Dog(Animal):pass

hua = Cat('小花','橘猫')
print(hua)
print(hua.name)
print(hua.kind)
hua.eat('小鱼干')

hei = Dog('小黑','中华田园犬')
print(hei.name)
print(hei.kind)
hei.eat('单身狗粮')

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

    def eat(self,food):
        print('%s eat %s'%(self.name,food))

class Cat(Animal):
    def __init__(self,name,kind,eyes_color):
        self.eyes_color = eyes_color
        Animal.__init__(self,name,kind)   # 在子类和父类有同名方法的时候,默认只执行子类的方法
        # 如果想要执行父类的方法,可以在子类的方法中再 指名道姓 的调用父类的方法

class Dog(Animal):pass

hua = Cat('小花','橘猫','蓝色')
print(hua.__dict__)
当Cat自己拥有__init__的时候,就不再调用父类的了

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

    def eat(self,food):
        print('%s eat %s'%(self.name,food))

class Cat(Animal):
    def __init__(self,name,kind,eyes_color):
        self.eyes_color = eyes_color
        # super(Cat,self).__init__(name,kind)
        # super().__init__(name,kind)   # 相当于执行父类的init方法
        # Animal.__init(self,name,kind)

class Dog(Animal):pass

hua = Cat('小花','橘猫','蓝色')
print(hua.__dict__)

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

    def eat(self,food):
        print('%s eat %s'%(self.name,food))

    def drink(self):
        print('%s drink water'%(self.name))

    def catch(self):
        print('%s catch mouse'%(self.name))

class Cat(Animal):
    def __init__(self,name,kind,eyes_color):
        self.eyes_color = eyes_color  # 派生属性
        # super(Cat,self).__init__(name,kind)
        super().__init__(name,kind)   # 相当于执行父类的init方法
        # Animal.__init(self,name,kind)

    def climb(self):              # 派生方法
        print('%s climb tree'%self.name)

class Dog(Animal):
    def chai(self):
        print('%s cha'%(self.name))

hua = Cat('小花','橘猫','蓝色')
hua.eat('小鱼干')
hua.climb()

子类 父类

子类的对象

想要使用某一个名字

  1. 如果自己有 就用自己的
  2. 如果自己没有 就用父类的
  3. 如果父类也没有 就报错
    ####如果想要使用的名字父类子类都有
  4. 既想使用子类的,也想使用父类的,那就在子类的方法中使用
    1. 父类名.方法名(self,参数1,参数2)
    2. super().方法名(参数1,参数2)
class A:pass
class A(object):pass
print(A.__bases__)
object类
object类是A的父类
#在python3当中,所有的类都继承object类,所有的类都是新式类
#所有的类的类祖宗 都是object
#父类是object的类 —— 新式类

class A(object):
    pass

a = A()   # 总是要调用init的,如果我们不写,实际上就调用父类object的__init__方法了

人狗大战

class Animal(object):
   def __init__(self,name,blood,ad):
       self.name = name
       self.hp = blood
       self.ad = ad
class Dog(Animal):
   def __init__(self,name,blood,ad,kind):
       super().__init__(name,blood,ad)
       self.kind = kind

   def bite(self,person):
       person.hp -= self.ad
       print('%s攻击了%s,%s掉了%s点血' % (self.name, person.name, person.name, self.ad))

class Person(Animal):
   def __init__(self,name,hp,ad,sex):
       super().__init__(name,hp,ad)
       self.sex = sex

   def fight(self,dog):
       dog.hp -= self.ad
       print('%s攻击了%s,%s掉了%s点血'%(self.name,dog.name,dog.name,self.ad))

hei = Dog('小黑',300,20,'哈士奇')
alex = Person('alex',20,1,'不详')
alex.fight(hei)
print(hei.hp)
hei.bite(alex)
print(alex.hp)

抽象

继承

  • 组合 :什么有什么
  • 继承 :什么是什么的关系
    1. 先想描述的对象
    2. 先写出对象所对应的类
    3. 发现多个类之间有相同的代码
    4. 把相同的代码提取出来,搞成一个父类

先抽象,再继承

对象 -->类 -->基类

基类 -继承-> 子类 -实例化-> 对象

多继承

各种动物,每一种动物都是一个类

1. 青蛙、天鹅、老虎、鹦鹉
2. 青蛙 :走,游泳
3. 天鹅 :走,游泳,飞
4. 老虎 :走,游泳
5. 鹦鹉 :走,飞,说话
class FlyAnimal:
    def fly(self):pass
class SwimAnimal:
    def swim(self):pass
    def eat():pass
class WalkAnimal:
    def walk(self):pass
    def eat():pass

class Frog(SwimAnimal,WalkAnimal): pass
class Tiger(SwimAnimal,WalkAnimal):pass
class Swan(FlyAnimal,SwimAnimal,WalkAnimal):pass
class Parrot(FlyAnimal,WalkAnimal):
    def talk(self):
        pass
  • 多继承 是python语言中特有的继承方式
  • java语言中不支持多继承的,C#也不支持多继承
  • C++支持多继承

多继承和单继承是一样的

  1. 如果对象使用名字
  2. 是子类中有的,那么一定用子类的
  3. 子类没有,可以到多个父类中去寻找
    ##如果多个和父类都有,那么用谁的

钻石继承问题

class A(object):
    def func(self):
        print('a')

class B(A):
    pass
    # def func(self):
    #     print('b')

class C(A):
    pass
    # def func(self):
    #     print('c')

class D(B,C):
    pass
    # def func(self):
    #     print('d')

d = D()
d.func()

乌龟继承问题

class A(object):
    def func(self):
        print('a')

class B(A):
    pass
    # def func(self):
    #     print('b')

class C(A):
    pass
    # def func(self):
    #     print('c')

class D(B):
    pass
    # def func(self):
    #     print('d')

class E(C):
    pass
    # def func(self):
    #     print('e')

class F(D,E):
    pass
    # def func(self):
    #     print('f')
f = F()
f.func()

广度优先

C3算法

99%的情况都可以用眼睛看出来

但是仍然有1%的情况是看不出来的

C3算法是怎么计算的

class A(object):
    def func(self):
        print('a')

class B(A):
    pass
    def func(self):
        print('b')

class C(A):
    pass
    def func(self):
        print('c')
class F:
    pass
    def func(self):
        print('f')

class D(A,F):
    pass
    # def func(self):
    #     print('d')

class E(B,C,F):
    pass
    def func(self):
        print('e')

class G(C,D):
    pass
    def func(self):
        print('g')

class H(E,G):
    pass
    def func(self):
        print('h')

print(H.mro())   # 就是帮助我们来展示c3算法的继承顺序

C3算法

A= [AO]
B = B ,B节点的父类对应的顺序
B = B ,A节点顺序
B = B ,[AO]
提取第一个点
   # 如果从左到右第一个类,
   # 在后面的继承顺序中也是第一个,或者不再出现在后面的继承顺序中
   # 那么就可以把这个点提取出来,作为继承顺序中的第一个类
B = [AO]
BA = [O]
B这个节点的继承顺序 :[BAO]

C = C,[AO]
C = [AO]
CA = [O]
C这个节点的继承顺序 :[CAO]

l(D) = D + [BAO]
D = [BAO]
[DBAO]

l(E) = E + [CAO]
[ECAO]

L[F] = F,[DBAO],[ECAO]
[F] = [DBAO],[ECAO]
[FD] = [BAO],[ECAO]
[FDB] = [AO],[ECAO]
[FDB] = [AO],[ECAO]
[FDBE] = [AO],[CAO]
[FDBEC] = [AO],[AO]
[FDBECA] = [O],[O]
[FDBECAO]

经典类和新式类

  • py2.7 经典类
  • 2个图
    1. 看 C3 mro
    2. 你自己去网上找一张图
class A(object):
    def func(self):
        print('a')

class B(A):
    pass
    def func(self):
        super().func()
        print('b')

class C(A):
    pass
    def func(self):
        super().func()
        print('c')

class D(B,C):
    pass
    def func(self):
        super().func()
        print('d')

b = B()
b.func()
#在多继承中,super就只和mro顺序有关系,和父类子类没有关系了

总结

  • python的继承
  • 提高代码的重用性,减少了代码的冗余
  • 单继承
    1. 子类有的就用子类的
    2. 没有的就用父类的
    3. 如果父类子类都想用,super(),父类名.方法名
  • 多继承
    • 新式类 :继承object

      1. py2 要主动继承object才是新式类,默认是经典类
      2. 遵循的是广度优先算法,C3算法
      3. 有super()的,super遵循mro顺序的
      4. 有mro()方法
    • 经典类 :不继承object
      1. 多个类之间去寻找方法的时候遵循深度优先
      2. 没有super方法也没有mro

2019-03-27-day020-单继承与多继承的更多相关文章

  1. 2019.03.27 读书笔记 关于GC垃圾回收

    在介绍GC前,有必要对.net中CLR管理内存区域做简要介绍: 1. 堆栈:用于分配值类型实例.堆栈主要操作系统管理,而不受垃圾收集器的控制,当值类型实例所在方法结束时,其存储单位自动释放.栈的执行效 ...

  2. 2019.03.27【GDOI2019】模拟 T3

    题目大意 给出$n$, $p$, 求有多少长度为$n$的排列可以被分成三个上升子序列, 数量对$p$取模, 数据范围 $3 \leq n \leq 500$. 思路 首先让我们考虑如果有一个排列,如何 ...

  3. python学习 day20 (3月27日)----(单继承多继承c3算法)

    继承: 提高代码的重用性,减少了代码的冗余 这两个写法是一样的 Wa('青蛙').walk() #青蛙 can walk wa = Wa('青蛙') wa.walk() #青蛙 can walk 1. ...

  4. Lua面向对象----类、继承、多继承、单例的实现

    (本文转载)学习之用,侵权立删! 原文地址   http://blog.csdn.net/y_23k_bug/article/details/19965877?utm_source=tuicool&a ...

  5. C++对象模型:单继承,多继承,虚继承

    什么是对象模型 有两个概念可以解释C++对象模型: 语言中直接支持面向对象程序设计的部分.对于各种支持的底层实现机制. 类中成员分类 数据成员分为静态和非静态,成员函数有静态非静态以及虚函数 clas ...

  6. C++在单继承、多继承、虚继承时,构造函数、复制构造函数、赋值操作符、析构函数的执行顺序和执行内容

    一.本文目的与说明 1. 本文目的:理清在各种继承时,构造函数.复制构造函数.赋值操作符.析构函数的执行顺序和执行内容. 2. 说明:虽然复制构造函数属于构造函数的一种,有共同的地方,但是也具有一定的 ...

  7. JAVA之旅(六)——单例设计模式,继承extends,聚集关系,子父类变量关系,super,覆盖

    JAVA之旅(六)--单例设计模式,继承extends,聚集关系,子父类变量关系,super,覆盖 java也越来越深入了,大家加油吧!咱们一步步来 一.单例设计模式 什么是设计模式? JAVA当中有 ...

  8. [2019.03.25]Linux中的查找

    TMUX天下第一 全世界所有用CLI Linux的人都应该用TMUX,我爱它! ======================== 以下是正文 ======================== Linu ...

  9. 2019.03.03 - Linux搭建go语言交叉环境

    编译GO 1.6版本以上的需要依赖GO 1.4版本的二进制,并且需要把GOROOT_BOOTSTRAP的路径设置为1.4版本GO的根目录,这样它的bin目录就可以直接使用到1.4版本的GO 搭建go语 ...

  10. Alpha冲刺(4/10)——2019.4.27

    所属课程 软件工程1916|W(福州大学) 作业要求 Alpha冲刺(4/10)--2019.4.27 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪 ...

随机推荐

  1. Runable和Thread

    Java多线程 java中有两种实现多线程的方式: 1. 一种是通过继承Thread类,同时重写run()方法.但是java中,只允许单继承,也就是一个类只能继承一个父类,使得该方式具有一定的局限性, ...

  2. js中去掉字符串的空格、回车换行

    //例如下面这个json串,中间的\n表示换行 var str = "{' retmsg':'success ',\n' trans_date':' 20170906'}"; co ...

  3. hashCode会出现负数吗,答案是肯定的

    先来普及一下基本数据类型的长度: unsigned   int   0-4294967295   int   -2147483648-2147483647 unsigned long 0-429496 ...

  4. git相关知识(github,idea等的配置)

    本地git提交文件到github上: 1.在github上创建项目 2.使用git clone https://github.com/xxxxxxx/xxxxx.git克隆到本地 3.编辑项目 4.g ...

  5. Hadoop格式化 From hu-hadoop1/192.168.11.11 to hu-hadoop2:8485 failed on connection exception: java.net.

    192.168.11.12:8485: Call From hu-hadoop1/192.168.11.11 to hu-hadoop2:8485 failed on connection excep ...

  6. iOS 如何优化项目

    原文 前言 在项目业务趋于稳定的时候,开发完迭代需求后,我们可能会无所适从,进入一段空白期,但是对于攻城狮来说闲暇不是件好事,所以我们可能总想学点什么,却又没有头绪.这个时候我们就可以考虑完善和优化我 ...

  7. Java Web(六) JSP

    现在的Java Web开发已经很少使用JSP脚本了,业务逻辑都交给Servlet处理,JSP只负责显示视图,所以接下来的内容就对JSP脚本不做叙述了... JSP概述 JSP全名为Java Serve ...

  8. CAD绘制栏杆5.10

    REC绘制一个矩形,(40,40)回车.通过它的中点移动到扶手的中点用移动工具把它往右边稍微移动.在三维图中EXT命令拉伸它,拉到扶手底面.如图选择三维扶手,右击,加栏杆,选择我们绘制的栏杆,单元宽度 ...

  9. 请问微信小程序let和var以及const有什么区别

    在JavaScript中有三种声明变量的方式:var.let.const. var:声明全局变量,换句话理解就是,声明在for循环中的变量,跳出for循环同样可以使用. [JavaScript] 纯文 ...

  10. IDE 版本

    BDS 5 2007 D11  VER180 and VER185 RAD Studio 8 XE D15  VER 220 RAD 18 XE 10.1 Berlin D24  VER310  St ...