python3--object类,继承与派生,super方法,钻石继承问题

发布时间:2018-04-13 20:38:05编辑:Run阅读(1914)

昨天内容复习

组合:什么有什么的关系(例:老师有生日)class Birthday:

def __init__(self, year, month, day):

self.year = year

self.month = month

self.day = day

def fmt(self):

return '{}-{}-{}'.format(self.year, self.month, self.day)

class Teacher:

def __init__(self, name, birth):

self.name = name

self.birthday = birth

def birth_month(self):

self.birthday.fmt()  # 引用组合对象的方法

return self.birthday.month  # 引用组合对象的属性

birth = Birthday(1979, 10, 20)

sam = Teacher('Tom', birth)  # 将对象birth传进来作为实例化Teacher的属性

print(sam.birthday.year)  # 调用组合对象中的属性

print(sam.birthday.fmt())  # 调用组合对象中的方法

执行结果

1979

1979-10-20

总结:组合就是把一个对象,作为另外一个类的属性

继承

属性:名字 性别,品种

方法:吃 喝 爬树

属性:名字 性别 品种

方法:吃 喝 看门

例class Animal:

def __init__(self, name, sex, kind):

self.name = name

self.sex = sex

self.kind = kind

def eat(self):

print('{} is eating'.format(self.name))

def drink(self):

print('{} is drinking'.format(self.name))

class Cat(Animal):

def climb(self):

print('{} is climbing'.format(self.name))

class Dog(Animal):

def watch_door(self):

print('{} is watching door'.format(self.name))

# 1 确认自己没有init方法

# 2 看看有没有父类

# 3 发现父类Animal有init

# 4 看着父类的init方法来传参数

tom = Cat('小黑', '公', '波斯猫')

sam = Dog('旺财', '公', '哈士奇')

print(Cat.__dict__)  # Cat.__dict__ Cat类的命名空间中的所有名字

print(tom.__dict__)  # tom.__dict__ 对象的命名空间中的所有名字

print(Dog.__dict__)  # Dog.__dict__ Dog类的命名空间中的所有名字

print(sam.__dict__)  # sam.__dict__ 对象的命名空间中的所有名字

tom.eat()

tom.climb()

sam.drink()

sam.watch_door()

执行结果

{'climb':

{'kind': '波斯猫', 'name': '小黑', 'sex': '公'}

{'__doc__': None, '__module__': '__main__', 'watch_door':

{'kind': '哈士奇', 'name': '旺财', 'sex': '公'}

小黑 is eating

小黑 is climbing

旺财 is drinking

旺财 is watching door

object类class A:pass

a = A()

print(A.__bases__)

执行结果,可以看到A的父类为object,在python3中,只有新式类,默认继承object类

(

上面代码的执行步骤

1 创建了一个空的对象

2 调用init方法 -- class A里面没有写init方法,怎么不报错?执行了父类object的__init__方法

3 将初始化之后的对象返回调用出

在python3中所有的类都继承了object类

查看object的源码

里面包含了__init__方法

object带双下划线的方法,有2个名字,比如双下方法,魔术方法

任何实例化都经历3步,如果类没有init,由object完成了

例1class Animal:

def __init__(self, name, hp, ad):

self.name = name

self.hp = hp

self.ad = ad

def eat(self):

print('{}吃药回血了'.format(self.name))

class Person(Animal):

def attack(self, dog):  # 派生方法

print('{}攻击了{}'.format(self.name, dog.name))

class Dog(Animal):

def bite(self, person):  # 派生方法

print('{}咬了{}'.format(self.name, person.name))

sam = Person('Sam', 10, 20)  # 实例化一个对象sam,

dog = Dog('花花', 10, 5)     # 实例化一个对象dog

print(sam.__dict__)

print(dog.__dict__)

执行结果,打印对象属性

{'hp': 10, 'name': 'Sam', 'ad': 20}

{'hp': 10, 'name': '花花', 'ad': 5}

子类有的方法,叫派生方法

比如人有sex,狗有kind,现在需要在上面的例子中,给人额外加一个属性,狗额外加一个属性,那么首先想到的是在init里面加,如下

例class Animal:

def __init__(self, name, hp, ad):

self.name = name

self.hp = hp

self.ad = ad

def eat(self):

print('{}吃药回血了'.format(self.name))

class Person(Animal):

def __init__(self, sex):

self.sex = sex

def attack(self, dog):  # 派生方法

print('{}攻击了{}'.format(self.name, dog.name))

class Dog(Animal):

def __init__(self, kind):

self.kind = kind

def bite(self, person):  # 派生方法

print('{}咬了{}'.format(self.name, person.name))

sam = Person('男')  # 实例化类Person,传一个参数性别

dog = Dog('哈士奇')  # 实例化类Dog,传一个参数品种

print(sam.__dict__)  # 打印对象sam的属性

print(dog.__dict__)  # 打印对象dog的属性

执行结果

{'sex': '男'}

{'kind': '哈士奇'}

why?为什么之前的属性都没有了,因为自己有了init后,它不会执行父类的init方法,那么如何执行父类的init呢?

有两种方法,第一种class Animal:

def __init__(self, name, hp, ad):

self.name = name

self.hp = hp

self.ad = ad

def eat(self):

print('{}吃药回血了'.format(self.name))

class Person(Animal):

def __init__(self, name, hp, ad, sex):

Animal.__init__(self, name, hp, ad)

self.sex = sex

def attack(self, dog):  # 派生方法

print('{}攻击了{}'.format(self.name, dog.name))

class Dog(Animal):

def __init__(self, name, hp, ad, kind):

Animal.__init__(self, name, hp, ad)

self.kind = kind

def bite(self, person):  # 派生方法

print('{}咬了{}'.format(self.name, person.name))

sam = Person('Sam', 10, 20, '男')

dog = Dog('花花', 10, 5, '哈士奇')

print(sam.__dict__)

print(dog.__dict__)

执行结果

{'ad': 20, 'name': 'Sam', 'sex': '男', 'hp': 10}

{'kind': '哈士奇', 'ad': 5, 'name': '花花', 'hp': 10}

可以看到,父类的属性也继承了,自己添加的属性也有,怎么实现的?

当执行init之前,开辟内存空间,self执行的是同一块内存空间,sam里面的self,指向都是一样的,在同一个类里面,self指向的都是同一个,如下图

第二种写法class Animal:

def __init__(self, name, hp, ad):

self.name = name

self.hp = hp

self.ad = ad

def eat(self):

print('{}吃药回血了'.format(self.name))

class Person(Animal):

def __init__(self, name, hp, ad, sex):

super().__init__(name, hp, ad)

self.sex = sex

def attack(self, dog):  # 派生方法

print('{}攻击了{}'.format(self.name, dog.name))

class Dog(Animal):

def __init__(self, name, hp, ad, kind):

super().__init__(name, hp, ad)

self.kind = kind

def bite(self, person):  # 派生方法

print('{}咬了{}'.format(self.name, person.name))

sam = Person('Sam', 10, 20, '男')

dog = Dog('花花', 10, 5, '哈士奇')

print(sam.__dict__)

print(dog.__dict__)

执行结果

{'name': 'Sam', 'hp': 10, 'sex': '男', 'ad': 20}

{'name': '花花', 'hp': 10, 'kind': '哈士奇', 'ad': 5}

在单继承中,super负责找到当前类(也就是Person和Dog的父类Animal)所在的父类,在这个时候不需要再手动传self

修改上面例子,增加新的需求:人吃药要钱,狗吃药不要钱class Animal:

def __init__(self, name, hp, ad):

self.name = name

self.hp = hp

self.ad = ad

def eat(self):

print('eating in Animal')

self.hp += 20

class Person(Animal):

def __init__(self, name, hp, ad, sex):

super().__init__(name, hp, ad)

self.sex = sex

self.money = 100  # 设置初始钱为100

def attack(self, dog):  # 派生方法

print('{}攻击了{}'.format(self.name, dog.name))

def eat(self):

super().eat()  # super()方法找到父类,父类点eat(),执行父类里面的eat()方法

print('eating in Person')

self.money -= 50

class Dog(Animal):

def __init__(self, name, hp, ad, kind):

super().__init__(name, hp, ad)

self.kind = kind

def bite(self, person):  # 派生方法

print('{}咬了{}'.format(self.name, person.name))

sam = Person('Sam', 10, 20, '男')

dog = Dog('花花', 10, 5, '哈士奇')

sam.eat()

print(sam.__dict__)

print(dog.__dict__)

执行结果

eating in Animal

eating in Person

{'sex': '男', 'ad': 20, 'money': 50, 'name': 'Sam', 'hp': 30}

{'ad': 5, 'kind': '哈士奇', 'name': '花花', 'hp': 10}

继承

父类是新式类,那么继承的子类全部都是新式类,python3里面没有经典类

单继承 新式类

多继承 新式类(也叫钻石继承)

例子class A:

def func(self):

print('A')

class B(A):

def func(self):

print('B')

class C(A):

def func(self):

print('C')

class D(B,C):

def func(self):

print('D')

d = D()

d.func()

执行结果,why?

D

龟壳模型

新式类 多继承 寻找名字的顺序 遵循广度优先

super在多继承中,是找下一个节点的,而不是找父类的!

总结,在python3中都是新式类,使用的是广度优先原则

super()

在单继承中就是单纯的寻找父类

在多继承中就是根据子节点所在图的mro顺序寻找下一个类

例子class A:

def func(self):

print('A')

class B(A):

def func(self):

print('B')

class C(A):

def func(self):

print('C')

class D(B):

def func(self):

print('D')

class E(C):

def func(self):

print('E')

class F(D,E):

def func(self):

print('F')

st = F()

print(F.mro())

使用F.mro()打印出寻找类的顺序

[, , , , , , ]

在python2.x中,经典类多继承使用深度优先原则

在python2.x中,不手动继承object类,都属于经典类

深度优先,一条路走到底,找不到就会回来找其他的

经典类:在python2.x版本才存在,且必须不继承object

遍历的时候遵循深度优先算法

没有mro方法

没有super()方法

新式类:在python2.x版本中,需要继承object,才是新式类

遍历的时候遵循广度优先算法

在新式类中,有mro方法

有super()方法,但是在2.x版本的解释器中,必须传参数(子类名,子类对象)

关键字:

python 钻石继承_python3--object类,继承与派生,super方法,钻石继承问题相关推荐

  1. Java SE_封装、继承、object类、super-this关键字、方法重写、多态、instanceof、类型转换

    封装 该露的露,该藏的藏 我们程序设计要追求"高内聚,低耦合".高内聚:类的内部数据操作细节自己完成,不允许外部干涉:低耦合:仅暴露少量的方法给外部使用. 封装(数据的隐藏) 通常 ...

  2. Java:继承之super关键字,继承之私有权限,继承之方法重写,继承之object类,继承之简单工厂模式

    一.继承的概念及用法       继承背后的思想就是        基于已存在的类来构建新类         当从已存在类继承时,就重用了它的方法和属性,还可以添加新的方法和属性来定制新类以应对需求 ...

  3. Java继承之object类、继承小练习和继承简单工厂模式

    1.object类常见方法 (1)Java中,所有类都直接或间接继承自java.lang.Object类,Object类可以说是Java中所有类的祖先即根类 (2)Java中任何类都继承了Object ...

  4. Java 实验报告 了解如何使用类及其成员的修饰符,理解类的继承性,掌握方法的继承、重载和覆盖

    班级软件16-2班 学号 3162052051734姓名梁振宇同组实验者 实验名称Java语言基础练习日期 2018年 05 月31 日 一.实验目的: 了解如何使用类及其成员的修饰符,理解类的继承性 ...

  5. Java实验报告 理解类的多态性,掌握方法的继承、重载和覆盖,掌握如何从键盘输入数据以及多重循环的使用

    桂 林 理 工 大 学 实  验  报  告 班级软件16-2班 学号 3162052051734姓名梁振宇同组实验者 实验名称Java语言基础练习日期 2018年 05 月31 日 一.实验目的: ...

  6. c++ 实现一个object类_说说Object类下面有几种方法呢?

    欢迎关注头条号:Java小野猫 今天说一道基础题型,不过很多人会忽略或者至少说不完整,但是面试时被问到的几率还是很大的. 面试题 Object有几种方法呢? Java语言是一种单继承结构语言,Java ...

  7. 【08期】说说Object类下面有几种方法呢?

    今天说一道基础题型,不过很多人会忽略或者至少说不完整,但是面试时被问到的几率还是很大的. 面试题 Object有几种方法呢? Java语言是一种单继承结构语言,Java中所有的类都有一个共同的祖先.这 ...

  8. java object 方法_Java中Object类常用的12个方法,你用过几个?

    前言 Java 中的 Object 方法在面试中是一个非常高频的点,毕竟 Object 是所有类的"老祖宗".Java 中所有的类都有一个共同的祖先 Object 类,子类都会继承 ...

  9. Object类中的两个方法——wait和notify使用总结

    Object类中的wait .和 notify方法是用来处理线程的方法,既然定义在Object类中,两个方法的重要程度可见一斑: 两个方法的使用上都很复杂:通过阅读API获得更多对方法的理解: The ...

  10. Python类与对象最全总结大全(类、实例、属性方法、继承、派生、多态、内建函数)

    目录 面向对象编程 常用术语/名词解释 抽象/实现 封装/接口 合成 派生/继承/继承结构 泛化/特化 多态 自省/反射 访问限制 私有属性和公有属性 私有方法的设置 类 创建类 声明与定义 类属性 ...

最新文章

  1. WINDOWS下调用GetTokenInformation的奇怪之处--两次调用
  2. 有向图的深度和广度遍历
  3. Java FilterInputStream skip()方法与示例
  4. 6 日期字符串转日期_山西省导游协会关于发放电子导游证的通知 (生成日期为2020年5月28日2020年6月3日)...
  5. RTX移植到STM32F103
  6. 你是否遇到过职业枯竭?
  7. 安卓9.0官方系统升级包_想升级鸿蒙系统都来看看!华为新系统升级名单曝光:有你手机吗?...
  8. GPUImageMovieWriter录制视频问题
  9. 使用脚本开启客户端远程桌面
  10. linux三剑客之awk
  11. android中所有颜色大全
  12. 区块链 以太坊 solidity 什么时候使用storage、memory
  13. java Monitor对象监视器、对象头、mark word
  14. 计算机在材料科学中的应用论文,计算机在材料科学中的应用论文(2)
  15. Chapter6 机器人系统仿真(Ⅰ)---使用rviz集成urdf、xacro建造机器人模型
  16. Anciety 0CTF/TCTF 2018 总结
  17. 【Mac使用技巧】Mac的VMware虚拟机系统时间如何调成不同步
  18. 文件的后缀名怎样重命名,重命名为大写字母
  19. ITRON的内存管理,中断处理,时钟管理
  20. [教你警告消除]Warning[Pe1072]: a declaration cannot have a label!

热门文章

  1. 弘辽科技:传统电商转型,要时刻做好准备
  2. 20180614 MATLAB环境下自动代码生成
  3. 图形学笔记(九)几何 ——几何表示方法(CSG、距离函数、水平集 、点云、网格(obj格式))、贝塞尔曲线(面)
  4. “坚持不一定成功,放弃一定会失败”--------王大爷
  5. gulp 压缩html文件,gulp压缩js
  6. 基于SSM框架图书管理系统开发与设计(附源码资料)-毕业设计
  7. java(7): 抽象类和接口区别
  8. 浅析tpm设备点检管理的八定原则及诊断五法
  9. java optional详解_java8中Optional的用法详解
  10. C语言实现逆波兰法计算表达式