封装

面向对象编程有三大特性:封装、继承、多态,其中最重要的一个特性就是封装。封装指的就是把数据与功能都整合到一起,针对封装到对象或者类中的属性,我们还可以严格控制对它们的访问,分两步实现:隐藏与开放接口,也就是后面出现的私有化属性和方法

# -*- coding: UTF-8 -*-
# @Date :2022/9/6 19:17 class School:
school_name = 'ShanXiPoliceCollege' def __init__(self, nickname, addr):
self.addr = addr
self.nickname = nickname
self.classes = [] def related(self, class_obj):
# self.classes.append(class_name)
self.classes.append(class_obj) def tell_class(self):
# 打印班级的名字
print(self.nickname.center(60, '='))
# 打印班级开设的课程信息
for class_obj in self.classes:
class_obj.tell_couse() """
# 创建学校
sch_obj1 = School('老男孩', '上海')
sch_obj2 = School('黑马程序员', '北京') # 开设班级
sch_obj1.related('脱产14期')
sch_obj2.related('脱产15期')
#查看每个校区开设的班级
sch_obj1.tell_class()
sch_obj2.tell_class()
# sch_obj1.tell_classes()
"""
sch_obj1 = School('老男孩', '上海')
sch_obj2 = School('黑马程序员', '北京')
sch_obj3 = School('千锋教育', '北京') class Class:
def __init__(self, name):
self.name = name
self.course = None def related_course(self, course_obj):
self.course = course_obj def tell_couse(self):
print('班级名:%s' % self.name, end=' ')
self.course.tell_info() # 打印课程的详细信息 # 创建班级
class_obj1 = Class('脱产14期')
class_obj2 = Class('脱产15期')
class_obj3 = Class('脱产16期')
# 2.为班级关联一个课程
# class_obj1.related_course('Python全栈开发')
# class_obj2.related_course('Linux运维')
# class_obj3.related_course('MySQL数据库') # 3.查看班级开设的课程
# class_obj1.tell_couse()
# class_obj2.tell_couse()
# class_obj3.tell_couse() # 4. 为学校开设班级
sch_obj1.related(class_obj1)
sch_obj2.related(class_obj2)
sch_obj3.related(class_obj2) # sch_obj2.tell_class()
# sch_obj1.tell_class() class Course:
def __init__(self, name, period, price):
self.name = name
self.period = period
self.price = price def tell_info(self):
print('<%s-%s-%s>' % (self.name, self.period, self.price)) # 三:课程
# 1.创建课程
course_obj1 = Course('Python全栈开发', '6months', 20000)
course_obj2 = Course('Linux运维', '5months', 15000)
course_obj3 = Course('MySQL数据库', '2months', 8000)
# 2.查看课程详细信息
# course_obj1.tell_info()
# course_obj2.tell_info() # 3.为班级关联课程对象
class_obj1.related_course(course_obj1)
class_obj2.related_course(course_obj2)
class_obj3.related_course(course_obj3) # 4.
# class_obj1.tell_couse()
# class_obj2.tell_couse()
# class_obj3.tell_couse() sch_obj1.tell_class()
sch_obj2.tell_class()
sch_obj3.tell_class()

继承

Python中展现面向对象的三大类型: 封装,继承,多

  1. 封装:值得是把内容封装到某个地方,便于后面的使用

    他需要:

    把内容封装到某个地方,从另外一个地方去到调用被封装的内容

    对于封装来说,其实就是使用初始化构造方法将内容封装到对象中,然后通过对象直接或者self来获取被封装的内容

  2. 继承:和现实生活当中的继承是一样的,也就是子可以继承父的内容【属性和行为】(爸爸有的儿子有, 相反, 儿子有的爸爸不一定有)。继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,新建的类可称为子类或派生类,父类又可称为基类或超类

  3. 所谓多态,定义时的类型和运行时的类型是不一样,此时就成为多态

单继承

class Animal:
def eat(self):
'''

'''
print('吃')
def drink(self):
'''

'''
print('喝') class Dog(Animal):#继承Animal父类, 此时Dog就是子类
def wwj(self):
print('汪汪叫')
class Cat(Animal):
def mmj(self):
print('喵喵叫')
d1=Dog()
d1.eat()#继承了父类的行为
d1.wwj()
c1=Cat()
c1.drink()
c1.eat() '''
对于面向对象的继承来说,其实就是将多个子类共有的方法提取到父类中,
子类仅仅需要继承父类而不必一一去实现
这样就可以极大提高效率,减少代码的重复编写,精简代码的层级结构 便于扩展 class 类名(父类):
pass
'''

通过类的内置属性__bases__可以查看类继承的所有父类

print(Dog.__bases__)

"""结果如下"""
(<class '__main__.Animal'>,)

多继承

class shenxian:
def fly(self):
print('神仙会飞') class Monkey:
def chitao(self):
print('猴子喜欢吃桃子')
class SunWuKong(shenxian,Monkey):
pass swk=SunWuKong()
swk.fly()
swk.chitao() #当多个父类当中存在相同方法时候,
class D:
def eat(self):
print('D.eat')
class C(D):
def eat(self):
print('C.eat')
class B(D):
pass
class A(B,C):
pass a=A()
# b=B()
a.eat()
print(A.__mro__)#可以现实类的依次继承关系 查找执行顺序
#在执行eat方法时,顺序应该是
#首先到A里面去找,如果A中没有,则就继续去B类中去查找,如果B中没有,则去C中查找,
#如果C类中没有,则去D类中查找,如果还没有找到,就会报错
#A-B-C-D 也是继承的顺序

在Python2中有经典类与新式类之分,没有显式地继承object类的类,以及该类的子类,都是经典类,显式地继承object的类,以及该类的子类,都是新式类。而在Python3中,即使没有显式地继承object,也会默认继承该类,如下

print(shenxian.__bases__)

"""结果如下"""
(<class 'object'>,)
提示:object类提供了一些常用内置方法的实现,如用来在打印对象时返回字符串的内置方法__str__

属性查找

有了继承关系,对象在查找属性时,先从对象自己的__dict__中找,如果没有则去子类中找,然后再去父类中找……

>>> class Foo:
... def f1(self):
... print('Foo.f1')
... def f2(self):
... print('Foo.f2')
... self.f1()
...
>>> class Bar(Foo):
... def f1(self):
... print('Foo.f1')
...
>>> b=Bar()
>>> b.f2()
Foo.f2
Foo.f1
"""
b.f2()会在父类Foo中找到f2,先打印Foo.f2,然后执行到self.f1(),即b.f1(),仍会按照:对象本身->类Bar->父类Foo的顺序依次找下去,在类Bar中找到f1,因而打印结果为Foo.f1
"""

父类如果不想让子类覆盖自己的方法,可以采用双下划线开头的方式将方法设置为私有的

>>> class Foo:
... def __f1(self): # 变形为_Foo__fa
... print('Foo.f1')
... def f2(self):
... print('Foo.f2')
... self.__f1() # 变形为self._Foo__fa,因而只会调用自己所在的类中的方法
...
>>> class Bar(Foo):
... def __f1(self): # 变形为_Bar__f1
... print('Foo.f1')
...
>>>
>>> b=Bar()
>>> b.f2() #在父类中找到f2方法,进而调用b._Foo__f1()方法,同样是在父类中找到该方法
Foo.f2
Foo.f1

继承实现原理

  1. 菱形问题,,或称钻石问题,有时候也被称为“死亡钻石”

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
  1. 继承原理

python到底是如何实现继承的呢? 对于你定义的每一个类,Python都会计算出一个方法解析顺序(MRO)列表,该MRO列表就是一个简单的所有基类的线性顺序列表,如下

>>> D.mro() # 新式类内置了mro方法可以查看线性列表的内容,经典类没有该内置该方法
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。

MRO列表并遵循如下三条准则:

1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类

所以obj.test()的查找顺序是,先从对象obj本身的属性里找方法test,没有找到,则参照属性查找的发起者(即obj)所处类D的MRO列表来依次检索,首先在类D中未找到,然后再B中找到方法test

1.由对象发起的属性查找,会从对象自身的属性里检索,没有则会按照对象的类.mro()规定的顺序依次找下去,
2.由类发起的属性查找,会按照当前类.mro()规定的顺序依次找下去,

重写父类方法

  • 所谓重写,就是子类中,有一个和父类相同名的方法,在子类中的方法会覆盖掉子类中同名的方法,
  • 为什么要重写,父类的方法已经不满足子类的需要,那么子类就可以重写父类或者完善父类方法

当父类的方法实现不能满足子类的时候,可以对方法进行重写

重写父类的方法有两种

  1. 覆盖父类方法
class Father:
def smoke(self):
print('抽芙蓉王')
def drink(self):
print('喝二锅头')
class Son(Father):
#与父类的(抽烟)方法同名,这就是重写父类方法
def smoke(self):
print('抽中华') #重写父类方法后,子类调用父类方法时,将调用的是子类的方法
son=Son()
son.smoke()
  1. 扩展父类方法

方法一:“指名道姓”地调用某一个类的函数

class Father:
def smoke(self):
print('抽芙蓉王') def drink(self):
print('喝二锅头') class Son(Father):
def drink(self):
##调用的是函数,因而需要传入self
Father.drink(self) s = Son()
s.drink()

方法二:super()

"""
调用super()会得到一个特殊的对象,该对象专门用来引用父类的属性,且严格按照MRO规定的顺序向后查找
"""
class Father:
def smoke(self):
print('抽芙蓉王') def drink(self):
print('喝二锅头') class Son(Father):
def drink(self):
#调用的是绑定方法,自动传入self
super().drink() s = Son()
s.drink() """结果如下"""
喝二锅头
class People:
school = '清华大学' def __init__(self, name, sex, age):
self.name = name
self.sex = sex
self.age = age class Teacher(People):
def __init__(self, name, sex, age, title): # 派生
#方法一
People.__init__(self, name, sex, age) # 调用的是函数,因而需要传入self
#方法二
super().__init__(name,age,sex) #调用的是绑定方法,自动传入self
self.title = title
def teach(self):
print('%s is teaching' % self.name)
obj = Teacher('lili', 'female', 28, '高级讲师') # 只会找自己类中的__init__,并不会自动调用父类的
print(obj.name)

这两种方式的区别是:方式一是跟继承没有关系的,而方式二的super()是依赖于继承的,并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找

#A没有继承B

class A:
def test(self):
super().test() class B:
def test(self):
print('from B') class C(A, B):
pass print(C.mro()) # 在代码层面A并不是B的子类,但从MRO列表来看,属性查找时,就是按照顺序C->A->B->object,B就相当于A的“父类” obj = C()
obj.test() # 属性查找的发起者是类C的对象obj,所以中途发生的属性查找都是参照C.mro() """结果如下"""
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
from B

obj.test()首先找到A下的test方法,执行super().test()会基于MRO列表(以C.mro()为准)当前所处的位置继续往后查找(),然后在B中找到了test方法并执行。

多态

  • 所谓多态,定义时的类型和运行时的类型是不一样,此时就成为多态
#要想实现多态,必须有两个前提需要遵守:
'''
1.继承:多态必须放生在父类和子类之间
2.重写:子类重写父类的方法
'''
class Animal:
'''
基类[父类]
'''
def say(self):
print('我是一个动物'*10)
class Dark(Animal):
'''
子类【派生类】
'''
def say(self):
'''
重写父类方法
'''
print('我是一个鸭子'*10)
class Dog(Animal):
def say(self):
print('我是一只'*10)
# dark=Dark()
# dark.say() #统一的去调用
def commonInvoke(obj):
obj.say()
list=[Dark(),Dog()]
for item in list:
'''
循环调用函数
'''
commonInvoke(item)

python-封装、继承、多态的更多相关文章

  1. Python 入门 之 面向对象的三大特性(封装 / 继承 / 多态)

    Python 入门 之 面向对象的三大特性(封装 / 继承 / 多态) 1.面向对象的三大特性: (1)继承 ​ 继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类又可以 ...

  2. python面向对象(封装,继承,多态)

    python面向对象(封装,继承,多态) 学习完本篇,你将会深入掌握 如何封装一个优雅的借口 python是如何实现继承 python的多态 封装 含义: 1.把对象的属性和方法结合成一个独立的单位, ...

  3. java面向对象(封装-继承-多态)

    框架图 理解面向对象 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程强调的是功能行为 面向对象将功能封装进对象,强调具备了功能的对象. 面向对象是基于面向过程的. 面向对象的特点 ...

  4. 浅谈学习C++时用到的【封装继承多态】三个概念

    封装继承多态这三个概念不是C++特有的,而是所有OOP具有的特性. 由于C++语言支持这三个特性,所以学习C++时不可避免的要理解这些概念. 而在大部分C++教材中这些概念是作为铺垫,接下来就花大部分 ...

  5. Java三大特性(封装,继承,多态)

    Java中有三大特性,分别是封装继承多态,其理念十分抽象,并且是层层深入式的. 一.封装 概念:封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别:将抽象得到的数据 ...

  6. php面向对象 封装继承多态 接口、重载、抽象类、最终类总结

    1.面向对象 封装继承多态  接口.重载.抽象类.最终类 面向对象 封装继承多态  首先,在解释面向对象之前先解释下什么是面向对象? [面向对象]1.什么是类? 具有相同属性(特征)和方法(行为)的一 ...

  7. Java基础——面向对象(封装——继承——多态 )

    对象 对象: 是类的实例(实现世界中 真 实存在的一切事物 可以称为对象) 类: 类是对象的抽象描述 步骤: 1.定义一个类 (用于 描述人:) ( * 人:有特征和行为) 2.根据类 创建对象 -- ...

  8. OOP三大核心封装继承多态

    OOP支柱 3 个核心:封装 继承 多态 封装就是将实现细节隐藏起来,也起到了数据保护的作用. 继承就是基于已有类来创建新类可以继承基类的核心功能. 在继承中 另外一种代码重用是:包含/委托,这种重用 ...

  9. Python设计模式 - 基础 - 封装 & 继承 & 多态

    面向对象的核心是对象,世间万物都可以看作对象,任何一个对象都可以通过一系列属性和行为来描述,可以包含任意数量和类型的数据或操作.类是用来描述具有相同属性和方法的所有对象的集合.类通常是抽象化的概念,而 ...

  10. C语言设计模式-封装-继承-多态

    快过年了,手头的工作慢慢也就少了,所以,研究技术的时间就多了很多时间,前些天在CSDN一博客看到有大牛在讨论C的设计模式,正好看到了,我也有兴趣转发,修改,研究一下. 记得读大学的时候,老师就告诉我们 ...

随机推荐

  1. Django提交时报错

    错误描述: RuntimeError at /saveBlog You called this URL via POST, but the URL doesn't end in a slash and ...

  2. 【学习笔记】Vins-Mono论文阅读笔记(二)

    估计器初始化简述 单目紧耦合VIO是一个高度非线性的系统,需要在一开始就进行准确的初始化估计.通过将IMU预积分与纯视觉结构进行松耦合对齐,我们得到了必要的初始值. 理解:这里初始化是指通过之前imu ...

  3. Shell分析日志文件

    文章转载自:https://mp.weixin.qq.com/s/o63aIM2p9rc2OjhxiC6wgA 1.查看有多少个IP访问: awk '{print $1}' log_file|sort ...

  4. Elasticsearch:管理 Elasticsearch 内存并进行故障排除

    文章转载自:https://elasticstack.blog.csdn.net/article/details/116974695

  5. echarts BAR堆叠图显示百分比

    在使用echarts的堆叠图时,我们鼠标悬停的浮窗里的信息可能并不是我们想要的信息,这个时候需要我们配置一下,因为堆叠图的trigger的类型是坐标轴触发的,数据是多组数据,所以我们需要遍历一下数据, ...

  6. echarts 改变个别省份的边界线颜色

    想要实现地图,首先要引入china.js文件,如果有引入就直接调过本步骤去下方看代码,没有引入可以点击下方链接自行Ctrl c + Ctrl v china.js import "../.. ...

  7. 小程序uni-app发起网络异步请求

    // uni.request({ // url: 'api/boxs/search', // // 使用监听函数防止this指向改变 // success: res => { // // 判断是 ...

  8. 【pytest官方文档】解读- 插件开发之hooks 函数(钩子)

    上一节讲到如何安装和使用第三方插件,用法很简单.接下来解读下如何自己开发pytest插件. 但是,由于一个插件包含一个或多个钩子函数开发而来,所以在具体开发插件之前还需要先学习hooks函数. 一.什 ...

  9. 图解 | 聊聊 MyBatis 缓存

    首发公众号-悟空聊架构:图解 | 聊聊 MyBatis 缓存 你好,我是悟空. 本文主要内容如下: 一.MyBatis 缓存中的常用概念 MyBatis 缓存:它用来优化 SQL 数据库查询的,但是可 ...

  10. 齐博x1头部底部菜单高亮设置

    下面这段是默认模板头部的导航菜单: {php}$menu_choose=config('system_dirname')?config('system_dirname'):'index';{/php} ...