派森编程学习笔记“上帝视角下的游戏操盘手” 【自学笔记】

继承

在Python中继承是指:在类的基础上,它可以实现现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

编写类时,不一定非得从零开始,可以使用继承,一个类继承另一个类时,它将自动获得另一个类的所有属性和方法,原有的类称为父类、超类、基类多种叫法,而新类称为子类或派生类。 子类继承了其父类的所有属性和方法,同时也可以定义属于自己的属性和方法,继承的过程,就是从一般到特殊的过程。

重用现有类的功能,并在此基础上进行扩展。子类直接具有父类的成员(共性),还可以扩展新功能。耦合度高,父类的变化可以直接影响子类。

父类相对于子类更抽象,范围更宽泛,子类相对于父类更具体,范围更狭小。

看一段使用了继承的代码:

class Cat(object):def __init__(self):self.color = 'red'def run(self):print('猫咪今天很活泼')# 子类
class Cat_son(Cat):passcat = Cat_son()
print('小猫的颜色是' + cat.color)
cat.run()

在Cat()类的括号里我们写了一个object

在Python中创建类,在类名的后面可以加括号也可以不加,建议是加上括号。加上括号,里面可以继承其他的类,继承了object的类是新式类,object是所有内建类型的父类。


在Cat_son()这个类中,继承了Cat()类的属性和方法,创建Cat_son()类的实例化对象后可以直接调用Cat()类中的属性和方法。

单继承

单继承:子类只允许继承一个父类,这样的继承方式在于其继承有序,逻辑结构清晰、语法简单且隐患少,而缺点则是子类的功能只能在当前唯一的继承中扩展。

但是父类可以同时被多个子类继承,和每一个类可以创建无限个实例化对象相同。

class Person():def __init__(self):# 实例属性self.name = '大白'# 实例方法def run(self):print(self.name + '在跑步!')# 创建Student类,继承Person类,Person类为父类,Student类为子类
class Student(Person):# 子类可以继承父类中的所有方法和属性,即使子类没有自己的方法和属性pass# 创建子类的实例化对象
s1 = Student()
# 子类直接使用父类的方法
s1.run()
# 子类直接使用父类的属性
print(s1.name)

虽然子类Student()中没有定义__init__()方法初始化属性,也没有定义实例方法,但是父类有。所以只要创建子类的实例化对象,就默认执行了继承自Person()类的__init__()方法。

我们可以使用**isinstance()**函数来判断某个实例对象是否属于某个类。注意:是实例对象。具体用法是传入两个参数,第一个参数是实例对象名,第二个对象是类名,输出的是True或者False。

class Person():def __init__(self):# 实例属性self.name = '大白'class Student(Person):pass# 创建子类的实例化对象
s1 = Student()#使用isinstance()判断s1是否属于Person()类
print(isinstance(s1,Person))

另外需要注意的一点:父类创建的实例化对象不属于子类,子类创建的实例化对象属于父类,而且他们所创建的实例化对象都属于object()类。

class Person():def __init__(self):# 实例属性self.name = '大白'class Student(Person):pass# 创建子类的实例化对象
s1 = Student()
p1 = Person()
#使用isinstance()判断s1是否属于Person()类
print(isinstance(s1,Person))
#使用isinstance()判断s1是否属于object
print(isinstance(s1,object))
#使用isinstance()判断p1是否属于object
print(isinstance(p1,object))

多重继承

多重继承:一个子类继承两个或者两个以上的父类,父类中的属性和方法同时被子类继承下来。

# Father父类
class Father(object):# 实例方法def hobby(self):print("我喜欢玩电子游戏。")# 实例方法def cook(self):print("我不喜欢做饭。")# Mother父类
class Mother(object):# 实例方法def cook(self):print("我喜欢做饭。")# 实例方法def hobby(self):print("我不喜欢玩电子游戏。")# 多继承,同时继承 Father 父类和 Mother 父类
class Son(Father, Mother):pass# 创建实例化对象
son = Son()
# 调用父类中的hobby方法
son.hobby()
# 调用父类中的cook方法
son.cook()

定义的Father()父类和Mother()父类中都有cook()方法和hobby()方法,在创建子类Son()的时候,括号里从左向右依次继承了Father()父类和Mother()父类。

多重继承可以继承多个父类,即可以继承所有父类的属性和方法,在定义子类的时候,将父类的名字写入到括号中即可。

通过上面这段代码我们可以得出,当继承多个父类时,如果父类中有相同的方法,那么子类会从左到右优先使用最先被继承的方法。

多个父类中,不重名的属性和方法不会有任何影响。

当子类继承父类后,如果子类不想使用父类的方法,可以通过重写来覆盖父类的方法。为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

# Father父类
class Father(object):# 实例方法def hobby(self):print("我喜欢玩电子游戏。")# 实例方法def cook(self):print("我不喜欢做饭。")# Mother父类
class Mother(object):# 实例方法def cook(self):print("我喜欢做饭。")# 实例方法def hobby(self):print("我不喜欢玩电子游戏。")# 多继承,同时继承 Father 父类和 Mother 父类
class Son(Father, Mother):def cook(self):print('我最不喜欢做饭了。')def hobby(self):print('我最不喜欢电子游戏了。')# 创建实例化对象
son = Son()
son.hobby()
son.cook()

多重继承不仅仅只可以继承两个父类,可以继承很多很多,只要都写到子类的括号中去就可以了,继承的优先级是从左往右,也就是所谓的就近原则。

多层继承

多层继承:继承也可以产生在两个及两个以上的层级之间,也就是父类-子类-孙子类(打比喻),或者是父类的父类,父类的爷爷类等等。

多重继承是继承的宽度扩展,而多层继承是继承的深度扩展。

类B继承了类A,类C继承了类B,类D继承了类C,这种继承方式就是多层继承。

class A(object):def play(self):print('A is playing!')class B(A):  # 继承类Adef play(self):  # 自动覆盖父类的此方法print('B is playing')class C(B):  # 继承Bdef play(self):print('C is playing')class D(C):  # 继承Cpassd = D()
d.play()

当有多层继承时,如果父类中有相同方法,那么子类会优先调用最先被继承的方法。我们修改一下代码确认一下是不是。

class A(object):def play(self):print('A is playing!')class B(A):  # 继承类Adef play(self):  # 自动覆盖父类的此方法print('B is playing')class C(B):  # 继承Basedef playing(self):print('C is playing')class D(C):  # 继承A,Bpassd = D()
d.play()

类B继承了类A,类C继承了类B,类D继承了类C,那么类D可以使用类C中的方法和属性,也可以使用类B中的方法和属性,也可以使用类A中的方法和属性。

当类D的实例化对象调用属性和方法时,会优先在自己的内部查找是否有该属性和方法,如果没有找到,那么它会自动向它的父类中寻找,如果没有,就会继续向父类的父类中查找,一直查找到object类中。如果到最后都没有找到,就说明对象没有该属性或方法,程序报错,如果找到就会返回找到的属性和方法,不再继续往上查找。

这就是多层继承的优先级,类属性和类方法的优先级一样。

菱形继承

当一个子类继承多个父类时,多个父类最终继承了同一个父类,这样的继承方式称为菱形继承,也叫做钻石继承。

class A(object):def play(self):print('A is playing!')class B(A):  # 继承类Adef play(self):print('B is playing')class C(A):  # 继承类Adef playing(self):print('C is playing')class D(A):  # 继承类Adef __init__(self):self.name = '大白'class E(B,C,D):  #继承类B、C、Dpasse = E()
e.play()
print(e.name)

在菱形继承中,也是根据就近原则进行寻找父类的属性和方法,一直向上寻找至object类。

子类重写父类的同名属性和方法

有时候父类的方法不能满足子类的需要,我们可以对子类的方法重写,具体的实现方式就相当于在子类中定义了一个和父类同名的方法并实现。重写之后只会对子类的方法调用,而不会调用父类的方法,遵守就近原则。

重写,有时又称覆盖,是一个意思,指的是对类中已有方法的内部实现进行修改。

如果我们在子类中重写了从父类继承来的类方法,那么当在类的外部通过子类对象调用该方法时,Python 总是会执行子类中重写的方法。

举个例子,鸟都是有翅膀的,都会飞,我们可以定义一个和鸟相关的类:

class Bird():#鸟有翅膀def isWing(self):print("鸟有翅膀")#鸟会飞def fly(self):print("鸟会飞")

但是,对于鸵鸟来说,它虽然也是鸟类,也有翅膀,但是它只会跑并不会飞,针对这种情况,我们再定义一个鸵鸟类继承Bird()类。

class Bird():#鸟有翅膀def isWing(self):print("鸟有翅膀")#鸟会飞def fly(self):print("鸟会飞")class Ostrich(Bird):# 重写Bird类的fly()方法def fly(self):print("鸵鸟不会飞")

可以看到,因为 Ostrich 继承自 Bird,因此 Ostrich 类拥有 Bird 类的 isWing() 和 fly() 方法。其中,isWing() 方法同样适合 Ostrich,但 fly() 明显不适合,因此我们在 Ostrich 类中对 fly() 方法进行重写。

事实上,如果我们在子类中重写了从父类继承来的类方法,那么当在类的外部通过子类对象调用该方法时,Python 总是会执行子类中重写的方法。

这就产生一个新的问题,即如果想调用父类中被重写的这个方法,该怎么办呢?

Python 中的类可以看做是一个独立空间,而类方法其实就是出于该空间中的一个函数。而如果想要全局空间中,调用类空间中的函数,只需要在调用该函数是备注类名即可。

class Bird():#鸟有翅膀def isWing(self):print("鸟有翅膀")#鸟会飞def fly(self):print("鸟会飞")class Ostrich(Bird):# 重写Bird类的fly()方法def fly(self):print("鸵鸟不会飞")# 创建Ostrich对象
ostrich = Ostrich()
#调用 Bird 类中的 fly() 方法
Bird.fly(ostrich)

此程序中,需要大家注意的一点是,使用类名调用其类方法,Python 不会为该方法的第一个 self 参数自定绑定值,因此采用这种调用方法,需要手动为 self 参数赋值。

通过类的继承学会了复用代码,减少代码冗余,提高编程效率。

2021-11-16派森编程学习笔记“上帝视角下的游戏操盘手” 通过类的继承学会了复用代码,减少代码冗余,提高编程效率。相关推荐

  1. Java 标准 I/O 流编程学习笔记(下)

    java I/O学习笔记(上):http://blog.csdn.net/guying4875/article/details/78485287 8.回推流:PushbackInputStream与P ...

  2. 【2016.11.16】HTML学习笔记

    先是学习了思维导图的使用方法,然后自学了HTML 下面是自学的笔记 转载于:https://www.cnblogs.com/shan01/p/6071081.html

  3. ES6学习笔记(二):教你玩转类的继承和类的对象

    文章目录 继承 super关键字 ES6中的类和对象的4个注意点: 总结 继承 程序中的继承: 子类可以继承父类的一些属性和方法 class Father { //父类constructor () { ...

  4. Cocos2d-x学习笔记三之飞机游戏详解之GameOver类的讲解

    游戏下载链接:http://download.csdn.net/detail/a402813378/6275427 这个Demo的最后一篇,是制作GameOver窗口,这个窗口是游戏结束的窗口,讲完这 ...

  5. Java编程学习笔记(一)

    编程学习笔记--JAVA背景(一) 文章目录 编程学习笔记--JAVA背景(一) 编程学习笔记--JAVA注意事项(二) (一)从Hello world 开始: (二) Java 开发注意事项和细节说 ...

  6. Linux与C++11多线程编程(学习笔记)

    多线程编程与资源同步 在Windows下,主线程退出后,子线程也会被关闭; 在Linux下,主线程退出后,系统不会关闭子线程,这样就产生了僵尸进程 3.2.1创建线程 Linux 线程的创建 #inc ...

  7. 【C#8.0 and .NET Core 3.0 高级编程学习笔记】

    @C#8.0 and .NET Core 3.0 高级编程学习笔记 前言 为了能精细地完成对C#语言的学习,我决定选择一本书,精读它,理解它,记录它.我想选择什么书并不是最重要的,最重要的是持之以恒的 ...

  8. SHELL编程学习笔记

    SHELL编程学习笔记 本文描述unix shell的各种应用实例,根据查阅资料和自我总结,作为自己今后复习的模板.本文搜集整理常用的shell应用实例,以例子详述unixshell部分命令的使用,着 ...

  9. 大数据第二阶段Python基础编程学习笔记(待完善)

    大数据第二阶段Python基础编程学习笔记(待完善) 第一章 Python基础语法 3.8 1-1Python概述 python基础部分: ●Python基础语法: 标识符,关键字,变量,判断循环.. ...

最新文章

  1. 第十、十一周项目二-存储班长信息的学生类
  2. python语言中with as的用法使用详解
  3. abaqus的python安装文件在哪_在abaqus2016中安装xlwt和xlrd库教程
  4. C#调用VC的DLL的接口函数参数类型转换一览表
  5. Anbox之Ubuntu18.04安装(二)
  6. Android类参考---Fragment(二)
  7. linux shell 将命令行终端输出结果写入保存到文件中
  8. Easy make - emake
  9. SpringCloud 微服务 (七) 服务通信 Feign
  10. 傻瓜攻略(二)——MATLAB数据挖掘之Apriori算法实现
  11. win7下安装nodejs
  12. UE4 VR 重置摄像机朝向
  13. mac删除ssh key_好用的mac终端命令仿真工具
  14. 仿真工具打开raw报cannot load library XXX.dll错误
  15. Chrome 浏览器常用设置及问题(vimium)
  16. fabs () 函数
  17. VS使用C++开发桌面程序
  18. Python报错ModuleNotFoundError: No module named ‘concurrent‘
  19. STL 源码分析之string(一)基础篇
  20. 国内外遥感类核心期刊汇总

热门文章

  1. 电脑桌面壁纸更换后不一会就变成黑屏
  2. 【spring】spring异步执行的使用与源码分析
  3. 最详细的北京摩托车上牌流程-自己跑流程
  4. 微信小程序 -- 订阅消息wx.requestSubscribeMessage
  5. Ubuntu换源操作+vim的下载
  6. linux怎么配置拨号上网,linux拨号上网怎么设置
  7. R语言 回归诊断几种方法
  8. 昆明半程马拉松:1名选手死亡5名选手昏迷(图)
  9. 无限级分类之迭代查找家谱树
  10. 线程池踩坑记 --load飙高的原因