day29 继承
一、property装饰器
应用场景1
当我们需要在类中定义一个属性,他本质是一种方法,但是我们要让他用起来像是一种数据
# 例 人类的BMI会随着身高或者体重的变化而变化,所以我们在每次修改身高体重时BMI都会动态的变化,但是Bmi本身又是一种数据,用起来以数据的方式会更清晰
class People:
def __init__(self, name, weight, height):
self.name = name
self.weight = weight
self.height = height
@property
def bmi(self):
return self.weight // (self.height ** 2)
obj = People('hz',70,1.82)
print(obj.bmi)
>>>21.0
应用场景2
当我们把类中的某个属性隐藏起来后,可以用property给他们关联查看,删除,修改的操作
class People:
def __init__(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_name(self, val):
if type(val) is not str:
print('必须传入str类型')
return
self.__name = val
def del_name(self):
print('不让删除')
# 通过property的方法给类的name属性关联查看,修改,删除操作(按顺序)
name=property(get_name,set_name,del_name)
obj = People('hz')
print(obj.name)
obj.name = 'lxt'
print(obj.name)
del obj.name
应用场景3(场景2优化)
class People:
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
@name.setter
def name(self, val):
if type(val) is not str:
print('必须传入str类型')
return
self.__name = val
@name.deleter
def name(self):
print('不让删除')
obj = People('hz')
print(obj.name)
obj.name = 'lxt'
print(obj.name)
del obj.name
二、继承介绍
定义
继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,新建的类可称为子类或派生类,父类又可称为基类或超类
继承:
优点:解决类与类之间代码冗余
缺点:将类耦合到一起
python支持多继承
优点:最大程度的重用父类的属性
缺点:
1 违背了人的思维习惯:继承表达的是一种‘是’什么的关系
2 代码的可读性变差
3 不建议使用多继承,有可能会引发可恶的菱形问题,扩展性变差
如果真的涉及到一个子类不避免的重用多个父类的属性,应该用Mixins
新式类和经典类
在Python2中有经典类与新式类之分,没有显式地继承object类的类,以及该类的子类,都是经典类,显式地继承object的类,以及该类的子类,都是新式类。而在Python3中,即使没有显式地继承object,也会默认继承该类
1 语法
类是为了减少程序的代码重复,而继承就是为了减少类之间的代码重复
我们要找到类之间的重复关系,就要先抽象出来类的属性,把重复的统一成父类
# 老师和学生都属于人类,可以把他们之间的共同属性提取出来放在人类里,再去继承人类
class People:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
class Student(People):
def __init__(self,name,age,sex,sno):
People.__init__(self,name,age,sex)#继承使用人类的属性
self.sno = sno
def choose_course(self,course_obj):
self.course = course_obj
class Teacher(People):
def __init__(self,name,age,sex,sarly,level):
People.__init__(self,name,age,sex)#继承使用人类的属性
self.sarly = sarly
self.level = level
def set_score(self,student_obj,valu):
print(f'{self.name}给{student_obj.name}打分:{valu}')
student_obj.score = valu
stu_obj = Student('hz',18,'male',21346)
tea_obj = Teacher('egon',111,'male',2000,10)
tea_obj.set_score(stu_obj,18)
print(stu_obj.score)
2 属性查找
对象的属性查找顺序是:对象本身,类,父类
3 继承的实现原理
3.1 菱形问题
大多数面向对象语言都不支持多继承,而在Python中,一个子类是可以同时继承多个父类的,这固然可以带来一个子类可以对多个不同父类加以重用的好处,但也有可能引发著名的 Diamond problem菱形问题(或称钻石问题,有时候也被称为“死亡钻石”),菱形其实就是对下面这种继承结构的形象比喻

这种继承结构下导致的问题称之为菱形问题:如果A中有一个方法,B和/或C都重写了该方法,而D没有重写它,那么D继承的是哪个版本的方法:B的还是C的?如下所示
class A(object):
def test(self):
print('from A')
class B(A):
def test(self):
print('from B')
class C(A):
def test(self):
print('from C')
class D(B,C):
pass
obj = D()
obj.test() # 结果为:from B
那么为什么是先继承B呢,想知道这个就必须了解python继承实现的原理
3.2 继承原理
python到底是如何实现继承的呢? 对于你定义的每一个类,Python都会计算出一个方法解析顺序(MRO)列表,该MRO列表就是一个简单的所有基类的线性顺序列表,如下
print(D.mro())
>>>[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。 而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类
3.3 深度优先和广度优先
非菱形结构

当我们的继承是非菱形结构时,不管是新式类还是经典类都是按照分支一个一个找下去最后找object
菱形结构

经典类:深度优先,会在检索第一条分支的时候就直接一条道走到黑,即会检索大脑袋(共同的父类)

新式类:广度优先,会在检索最后一条分支的时候检索大脑袋
day29 继承的更多相关文章
- day29 Pyhton 面向对象 继承进阶
一.内容回顾 初识继承 父类\基类\超类 子类\派生类 派生 :派生方法.派生属性 单继承 继承的语法class子类名(父类名) 解决开发中代码冗余的问题 子类继承了父类之后,可以调用父类中的方法 如 ...
- day29 元类及异常处理
元类及异常处理 元类 什么是元类 在python中,一切皆对象,对象是由类产生的,那么类是不是对象呢? 举例: class A: pass print(type(A)) # <class 'ty ...
- javaScript的原型继承与多态性
1.prototype 我们可以简单的把prototype看做是一个模版,新创建的自定义对象都是这个模版(prototype)的一个拷贝 (实际上不是拷贝而是链接,只不过这种链接是不可见,给人们的感觉 ...
- JavaScript的继承实现方式
1.使用call或apply方法,将父对象的构造函数绑定在子对象上 function A(){ this.name = 'json'; } function B(){ A.call(this); } ...
- javascript中的继承与深度拷贝
前言 本篇适合前端新人,下面开始...... 对于前端新手来说(比如博主),每当对js的对象做操作时,都是一种痛苦,原因就是在于对象的赋值是引用的传递,并非值的传递,虽然看上去后者赋值给了前者,他们就 ...
- 谈谈一些有趣的CSS题目(四)-- 从倒影说起,谈谈 CSS 继承 inherit
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- JS继承类相关试题
题目一: //有关于原型继承的代码如下:function Person(name) { this.name = name;}Person.prototype = { getName : f ...
- JS继承之寄生类继承
原型式继承 其原理就是借助原型,可以基于已有的对象创建新对象.节省了创建自定义类型这一步(虽然觉得这样没什么意义). 模型 function object(o){ function W(){ } W. ...
- JS继承之借用构造函数继承和组合继承
根据少一点套路,多一点真诚这个原则,继续学习. 借用构造函数继承 在解决原型中包含引用类型值所带来问题的过程中,开发人员开始使用一种叫做借用构造函数(constructor stealing)的技术( ...
随机推荐
- 一文说通Dotnet Core的后台任务
这是一文说通系列的第二篇,里面有些内容会用到第一篇中间件的部分概念.如果需要,可以参看第一篇:一文说通Dotnet Core的中间件 一.前言 后台任务在一些特殊的应用场合,有相当的需求. 比方, ...
- throws,throw,try,catch,finally 分别代表什么 意义?
Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口. 在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例.当一个方法出现异常后便 抛出一个异 ...
- 基于session对象实现简单的购物车应用
大部分购物网站都会实现购物车的功能,基于session对象的购物车应用可以实现一个用户会话有效期内,用户所选多个商品的存储. 为了实现这样的功能需要编写三个JSP页面,分别是login.jsp.mai ...
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(11.0)- FlexSPI NOR启动时间(RT1170)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 FlexSPI NOR启动时间. 痞子衡刚刚拿到i.MXRT1170 B0版本的芯片,迫不及待地在上面跑了 ...
- Android开发Fragment的使用学习
基本概念 Fragment是Android3.0(API11)提出的概念,support-v4库中也开发了一套Fragment API,最低兼容Android 1.6.所以在开发中要注意不要导错包 导 ...
- vue+ajax的实现
html <tr> <td>用户名</td> <td id="t01"><input type="text" ...
- [ C++ ] 勿在浮沙筑高台 —— 内存管理(18~31p) std::alloc
部分内容个人感觉不是特别重要,所以没有记录了.其实还是懒 embedded pointers 把对象的前四字节当指针用. struct obj{ struct obj *free_list_link; ...
- redis高级命令1
设置name的过期时间是20秒 redis默认是16个数据库,默认是将数据存储在第0个数据库中 因为默认是0,当你选择其他数据的时候,是没有值的
- ThinkPHP5使用PHPExcel实现数据导出功能
1.将PHPExcel类库文件夹放入extend目录下 2.导出功能实现 public function download(){ if(request()->isPost()){ $val = ...
- Springboot 集成 ElasticSearch 踩坑
这里只涉及到基础使用 导包 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...