PythonOOP面向对象编程2
编程语言的特征:
- 继承
- 封装
- 多态
- 如:C++ / Java / Python / Swift / C#
inheritance 继承 drived 派生
概念:
- 继承是指从已有的类中衍生出新类,新类具有原类的行为,并能扩展新的行为
- 派生就是从一个已有的衍生(创建)新类,在新类上可以田间新的属性的行为
目的:
- 继承是延续旧类的功能
- 派生是为了在旧类的基础上添加新的功能
作用:
- 用继承派生机制,可以将一些共有功能加在基类中,实现代码的共享
- 在不改变基类的基础上改变原有功能
名词:
- 基类(base class)
- 超类(super class)
- 父类(father class)
- 派生类(derived class)
- 子类(child class)
说明:
- 任何类都直接或间接继承自object类
- object类是一切类的超类(祖类)不写相当于def Human(object):...
- 类的
__base__属性用来记录此类的基类
Human.__base__
单继承
- 语法:
语句块```
- 说明:
- 单继承是派生类由一个基类衍生出来的类
```python
# 此示例示意继承和派生
class Human:
'''此类用来描述人类的共性行为'''
def say(self, that):
print("说:", that)
def walk(self, distance):
print("走了:", distance, "公里")
print("\n-----人类-----")
h1 = Human()
h1.say("今天天气真热")
h1.walk(5)
class Student(Human):
def study(self, subject):
print("正在学习", subject)
print("\n-----学生-----")
s1 = Student()
s1.say("今天天气真热")
s1.walk(6)
s1.study("Python")
class Teacher(Student):
def teach(self, subject):
print("正在教", subject)
print("\n-----教师-----")
t1 = Teacher()
t1.say("明天就星期六啦")
t1.walk(8)
t1.teach("OOP")
t1.study("Piano")
-----人类-----
说: 今天天气真热
走了: 5 公里
-----学生-----
说: 今天天气真热
走了: 6 公里
正在学习 Python
-----教师-----
说: 明天就星期六啦
走了: 8 公里
正在教 OOP
正在学习 Piano
override 覆盖
概念:
- 覆盖是指在有继承关系的子类中,子类中实现了与基类同名的方法,在子类实例调用该方法时,实例调用的是子类中的覆盖版本的方法,这种现象叫做覆盖
子类对象显式调用基类方法的方式:
基类名.方法名(实例, 实际调用传参)
# 此示例示意覆盖的用法
class A:
def work(self):
print("A.work()被调用")
class B(A):
'''B类继承自A类'''
def work(self): # 在这里覆盖了A类的work方法
print("B.work()被调用")
pass
b = B()
b.work()
a = A()
a.work()
b.__class__.__base__.work(b)
B.work()被调用
A.work()被调用
A.work()被调用
super 函数
super(type, obj) 返回绑定超类的实例
super( ) 返回绑定超类的实例,等同于super(__class__, 实例方法的第一个参数)(必须在方法内调用)
# 此示例示意super函数来调用父类覆盖的用法
class A:
def work(self):
print("A.work()被调用")
class B(A):
'''B类继承自A类'''
def work(self):
print("B.work()被调用")
def super_work(self):
# self.work() # B.work()被调用
# super(B, self).work() # A.work()被调用
# super(__class__, self).work() # 在类内__class__可以直接用
# super().work()
b = B()
super(B, b).work() # 调用超类
b.super_work()
A.work()被调用
A.work()被调用
显式调用基类的__init__初始化方法:
- 当子类中实现了
__init__方法时,基类的__init__方法并不会被自动调用,此时需要显式调用
# 此实例示意子类对象用super方法显式调用基类__init__方法
class Human:
def __init__(self, n, a):
'''此方法为人的对象添加,姓名和年龄属性'''
self.name = n
self.age = a
def infos(self):
print("姓名:", self.name)
print("年龄:", self.age)
class Student(Human):
def __init__(self, n, a, s):
super().__init__(n, a)
self.score = s
def infos(self):
super().infos()
print("成绩:", self.score)
h1 = Human("小赵", 20)
h1.infos()
s1 = Student('小张', 18, 100)
s1.infos()
姓名: 小赵
年龄: 20
姓名: 小张
年龄: 18
成绩: 100
issubclass 判断派生子类
语法:
issubclass(cls, class_or_tuple)
判断一个类是否继承自其他类,如果此类cls是class或tuple中的一个派生子类,则返回True,否则返回False查看内建类的属性:
help(__builtins__)
class A:
pass
class B(A):
pass
class C(B):
pass
print(issubclass(C, B))
print(issubclass(C, A))
print(issubclass(C, object))
print(issubclass(C, (int, str)))
print(issubclass(C, (int, str, A)))
True
True
True
False
True
enclosure 封装
- 封装是指隐藏类的实现细节,让使用者不用关心这些细节,封装的目的是让使用者尽可能少的实例变量(属性)进行操作
- 私有属性:python类中,以双线划线'__'开头,不以双下划线结尾的标识符为私有成员,以类的外部无法直接访问
# 此示例示意使用私有属性和私有方法:
class A:
def __init__(self):
self.__p1 = 100 # __p1为私有属性,在类的外部不可调用
def test(self):
print(self.__p1)
def __m1(self):
print("我是A类的__m1方法")
a = A()
a.test()
a.__m1() # 在类调用不了__m1方法,访问失败
print(a.__p1) # 在类外看不到__p1属性,访问失败
100
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-17-a71fa418a07d> in <module>
12 a = A()
13 a.test()
---> 14 a.__m1()
15 print(a.__p1) # 在类外看不到__p1属性,访问失败
AttributeError: 'A' object has no attribute '__m1'
ploymorphic 多态
字面意思:“多种状态”
多态是指在继承/派生关系的类中,调用基类对象的方法,实际能调用子类的覆盖版本方法的现象叫多态
说明:
- 多态调用的方法与对象相关,不与类型相关
- Python的全部对象只有“运行时状态(动态)”,没有“C++/Java”里的编译时状态(静态)
class Shape():
def draw(self):
print("Shape.draw被调用")
class Point(Shape):
def draw(self):
print("正在画一个点")
class Circle(Point):
def draw(self):
print("正在画一个圈")
def my_draw(s):
s.draw() # 此处显示出多态的动态
# def my_draw(Circle s) # 在其他语言中,例如这样就是所谓的静态,在编译阶段规定类
# s.draw()
s1 = Circle()
s2 = Point()
my_draw(s1)
my_draw(s2)
正在画一个圈
正在画一个点
编程语言的特征:
- 继承
- 封装
- 多态
- 如:C++ / Java / Python / Swift / C#
multiple inheritance 多继承
多继承是指一个子类继承自两个或两个以上的基类
只有C++和Python支持多继承
语法:
class 类名(基类名1, 基类名2, ...): 语句块说明:
- 一个子类同时继承自多个父类,父类中的方法可以同时被继承下来
- 如果两个父类中有同名的方法,而在子类中由没有覆盖此方法时,调用结果难以确定
# 此示例示意多继承的语句和使用
class Car:
def run(self, speed):
print("汽车以", speed, "公里/小时的速度行驶")
class Plane:
def fly(self, height):
print("飞机以海拔", height, "的高度飞行")
class PlaneCar(Car, Plane):
pass
p1 = PlaneCar()
p1.fly(10000)
p1.run(50)
飞机以海拔 10000 的高度飞行
汽车以 50 公里/小时的速度行驶
- 缺陷:
- 标识符(名字空间冲突问题)
- 谨慎使用
- 标识符(名字空间冲突问题)
class A:
def m(self):
print("A.m()被调用")
class B:
def m(self):
print("B.m()被调用")
class AB(A, B):
pass
ab = AB()
ab.m()
A.m()被调用
MRO ( Method Resolution Order) 问题
- 类内的__mro__属性用来记录继承方法的查找顺序
# 此示例示意在多继承方法中的方法查找顺序问题
class A:
def m(self):
print("A.m")
class B(A):
def m(self):
print("B.m")
super().m()
class C(A):
def m(self):
print("C.m")
class D(B, C):
def m(self):
print("D.m")
super().m() ##
d = D()
print(D.__mro__)
d.m()
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
D.m
B.m
C.m
PythonOOP面向对象编程2的更多相关文章
- PythonOOP面向对象编程1
什么是对象? 对象是指现实中的物体或实体(拥有一系列变量.函数(方法)的) 什么事面向对象? 把一切看成对象(实例),让对象和对象之间建立关联关系 对象都有什么特征? 属性(名词)实例变量 姓名.年龄 ...
- PythonOOP面向对象编程3
override 函数重写 重写是在自定义的类内添加相应的方法,让自定义的类生成的对象(实例)像内建对象一样进行内建的函数操作 对象转字符串函数重写 repr(obj) 返回一个能代表此对象的表达式字 ...
- angular2系列教程(六)两种pipe:函数式编程与面向对象编程
今天,我们要讲的是angualr2的pipe这个知识点. 例子
- 带你一分钟理解闭包--js面向对象编程
上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...
- PHP 面向对象编程和设计模式 (1/5) - 抽象类、对象接口、instanceof 和契约式编程
PHP高级程序设计 学习笔记 2014.06.09 什么是面向对象编程 面向对象编程(Object Oriented Programming,OOP)是一种计算机编程架构.OOP 的一条基本原则是计算 ...
- Delphi_09_Delphi_Object_Pascal_面向对象编程
今天这里讨论一下Delphi中的面向对象编程,这里不做过多过细的讨论,主要做提纲挈领的描述,帮助自己抓做重点. 本随笔分为两部分: 一.面向对象编程 二.面向对象编程详细描述 ------------ ...
- python基础-面向对象编程
一.三大编程范式 编程范式即编程的方法论,标识一种编程风格 三大编程范式: 1.面向过程编程 2.函数式编程 3.面向对象编程 二.编程进化论 1.编程最开始就是无组织无结构,从简单控制流中按步写指令 ...
- 面向对象编程(OOP)
什么是面向对象编程,对于面向对象编程与面向过程编程的解释随处可见,个人认为对面向对象编程解释最好的一个定义是:依赖倒转原则是面向对象编程的标志,面向对象编程是一种思想,无论使用哪一种编程语言,如果在编 ...
- python 学习笔记7 面向对象编程
一.概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强..." ...
随机推荐
- ZOJ Problem Set - 3822Domination(DP)
ZOJ Problem Set - 3822Domination(DP) problemCode=3822">题目链接 题目大意: 给你一个n * m的棋盘,每天都在棋盘上面放一颗棋子 ...
- 视图中使用ROWNUM要注意
昨天晚上帮一位兄弟优化一个ebs的sql. sql有好几百行. SQL的样子是select .... from 视图 where ....过滤条件 视图的代码贴出来就不给大家看了,比較长.另外设计保密 ...
- Qwt库的一个使用注意事项
作者:朱金灿 来源:http://blog.csdn.net/clever101 一般debug版本的程序链接release版本的库是没有问题的.今天使用debug版本程序链接release版本的qw ...
- Android Retrofit+RxJava 优雅的处理服务器返回异常、错误
标签: 开始本博客之前,请先阅读: Retrofit请求数据对错误以及网络异常的处理 异常&错误 实际开发经常有这种情况,比如登录请求,接口返回的 信息包括请求返回的状态:失败还是成功,错误码 ...
- Jenkins学习总结(2)——Jenkins+Maven进行Java项目持续集成
最近配置了Jenkins服务器,记录下基本过程.(当然还遇到了若干小问题,兵来将挡水来土掩就是了) Jenkins安装 安装Tomcat 从Jenkins官网下载jenkins.war文件.官网地址: ...
- 【开卷故意】JAVA正則表達式模版
专业既然是机器学习.那工作肯定也是继续和数据打交道,那么问题来了,非常多时候推荐算法和数据挖掘算法都是现成可用的,平台初建,重点还在数据过滤和抽取.如何高效的抽取数据? 利用往常算法比赛中经常使用的字 ...
- Qt程序调试之Q_ASSERT断言(它是一个宏,接受布尔值,当其中的布尔值为真时,便什么也不做)
在使用Qt开发大型软件时,难免要调试程序,以确保程序内的运算结果符合我们的预期.在不符合预期结果时,就直接将程序断下,以便我们修改. 这就用到了Qt中的调试断言 - Q_ASSERT. 用一个小例子来 ...
- git- 仓库创建、修改、提交、撤销
1.仓库创建 zhangshuli@zhangshuli-MS-:~$ mkdir myGit zhangshuli@zhangshuli-MS-:~$ cd myGit/ zhangshuli@zh ...
- 洛谷 P3654 First Step (ファーストステップ)
洛谷 P3654 First Step (ファーストステップ) https://www.luogu.org/problemnew/show/P3654 题目描述 可是……这个篮球场,好像很久没有使用过 ...
- 【2017"百度之星"程序设计大赛 - 初赛(A)】今夕何夕
[链接]http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=775&pid=1005 [题意] 在这里写题意 [题 ...