笔记39 笨办法学python练习44继承inheritance与组合
一、指令准备
现在可以总结一点学习方法了,每个练习在做的过程中,凡是不太熟悉的指令符,都要查阅或者重温。这一点很难每次做到,但有这个要求非常必要。人大概都有自觉或者不自觉推脱省事的本性,不做要求,常常就会敷衍了事。反正是好玩不是谋生,在这种情况下要学到一点东西,更会有敷衍了事来纠缠。而且想学和能不能够学好也不是一回事情,花了大把功夫什么也不知的人应该是大有人在,这更会助长人敷衍了事的本性,切记。
上个练习就有pass,急于完成一个练习,没去查查。本次练习,代码开头就是这个pass,再偷闲可能就没有理由了。还很好查,在runoob.com网页上就有。
测试实例:
实例
#!/usr/bin/python # -- coding: UTF-8 -- # 输出 Python 的每个字母 for letter in ‘Python’: if letter == ‘h’: pass print ‘这是 pass 块’ print ‘当前字母 :’, letter print “Good bye!”
以上实例执行结果:
当前字母 : P
当前字母 : y
当前字母 : t
这是 pass 块
当前字母 : h
当前字母 : o
当前字母 : n
Good bye!
这个查阅,自然就明白pass的用途。
粗略地理解隐式函数implicit():这个implicit 关键字用于声明隐式的用户定义类型转换运算符。如果可以确保转换过程不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换。隐式转换可以通过消除不必要的类型转换来提高源代码的可读性。 但是,因为隐式转换不需要程序员将一种类型显式强制转换为另一种类型,所以使用隐式转换时必须格外小心,以免出现意外结果。 一般情况下,隐式转换运算符应当从不引发异常并且从不丢失信息,以便可以在程序员不知晓的情况下安全使用它们。
再粗略理解override函数,也只能是粗略,学、理解与用之间真有一段不短的距离。
什么是override?
override字面理解是无效,消除的意思,在Python里两个同名的方法但执行不同程序,其中一个方法使得另外一个方法无效的,这就叫override(重写)。
通常情况下,父类中的方法,而子类中有同名方法,在执行该方法时,调用的是该方法对应的类。
值得一提的是,这里父类和子类在原文中是superclass(总纲)和subclass(亚纲),用的是生物学术语,反应出计算机中的类与生物学分类的核心思想相似.
前面是隐式继承和显式覆盖,还有第三种继承的方式,那就是super(),覆盖的特例。
super() 函数是用于调用父类(超类)的一个方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
以下是 super() 方法的语法:
super(type[, object-or-type])
Python3.x 实例:
class A: def add(self, x): y = x+1 print(y) class B(A): def add(self, x): super().add(x) b = B() b.add(2) # 3
做了这些准备,再来敲代码,先敲ex44a.py,这是理解隐式继承的一个代码。
二、继承的五种不同情形
第一种隐式继承
这个ex44a,在父类定义了函数implicit(self),但在子类没有定义,于是,该练习执行时就会是子类继承父类的所有行为或者性质,所以有会话44a。
按照教材指示,调用ex44a中的行13,这让人又去巩固那个调用的涵义。本教材多次使用调用一次,给人明确的调用涵义理解的是练习40,这句话好像对我很有启示,“通过类你可以把一组函数和数据放到一个容器中,从而用“.”运算来启用它们。我理解,这里的启用应该和调用是一个意思吧,而在关于类的代码中,调用的一个符号标志就是那个”.”,访问和调用,应该是一个意思。
第二种显式覆盖
再来看ex44b,因为给予父子两类都有函数定义,结果就打出子类的函数。与ex44a相比,前者使用implicit,后者使用override,显然区别明显。也就让人理解了隐式继承和显式覆盖之间的不同。
给一个类一个定义就是给它一个函数,它在表示方法上却和更正规的函数并不相同,无需def,也无需冒号。本教材中,常以名称,也就是一个类,然后加上一个“.”带上implicit或者override这样一类函数在后。待慢慢消化。
第三种性质覆盖或者替换
基本上只换函数就可以做成这个44c,altered在这里只是一个函数名,用到的另一个函数是我们在先注意到的super。这个函数以Child和self两个参数被调用,调用之后再调用函数altered(),由此而可打印出PARENT altered()。
第四种组合式运用
那就是implicit,override 和super三种函数的组合使用,自然就是ex44d了。但排列顺序很重要,如果把隐式继承implicit放在前面,就只有一行可打印。重新按教材排列,结果就是如教材所言。
我再换一个次序,把super置前,看是什么结果?执行结果显示,altered之前执行结果和教材顺序的结果相同。
练习ex44e
在这里插入代码片class Parent(object):
def altered(self):
print("PARENT altered()")
def override(self):
print("PARENT override()")
def implicit(self):
print("PARENT implicit()")
class Child(Parent):
def override(self):
print("CHILD override()")
def altered(self):
print("CHILD, BEFORE PARENT.altered()")
super(Child, self).altered()
print("CHILD, AFTER PARENT.altered()")
dad = Parent()
son = Child()
dad.implicit()
son.implicit()
dad.override()
son.override()
dad.altered()
son.altered()
执行ex44e
```python
在这里插入代码片PS C:\Users\lenovo\1pythonw> python ex44e.py
PARENT implicit()
PARENT implicit()
PARENT override()
CHILD override()
PARENT altered()
CHILD, BEFORE PARENT.altered()
PARENT altered()
CHILD, AFTER PARENT.altered()
``但调换def次序,则执行有变
在这里插入代码片PS C:\Users\lenovo\1pythonw> python ex44d.py
PARENT implicit()
PARENT implicit()
PS C:\Users\lenovo\1pythonw> python ex44d.py
`
第五种多重继承multiple-inheritance in python
上段提到的super函数,可以用来理解python中的多重继承,即一个主体继承多个父类属性和方法的指令。最常见的是把super和基类中的_self_函数结合使用,在父类中实现所谓初始化,即那个init,然后再子类中操作。好像有点复杂,先做一点初始的理解。
刚简单看了一下那个mro,所谓方法解析顺序,估计在代码练习中才可能找到感觉,还是暂放一边。且看书中的又一个类组合的定义,这种类定义正好使用在本章的最后一个代码练习之中,那个ex44d我已经用了,这里用ex44.e来表示。不过,有点不明白这个代码为什么不把super()和_self_函数搭配使用。Super在这个ex44f中看不到了。
这里的两类关系值得思考,一类是A是B的关系,另一类是A中有B的关系。但这里的表述还是有点问题,父子类之间的关系,何以是A是B的关系呢?好像不能这么说,中国人和人这大概可以是A是B的关系,但上一代和下一代应该是平行的关系,而不是一个包含于的关系,更不是A中有B的关系。这大概牵涉到概念的定义问题,这里的父辈给人的感觉应该是比子类更大的类,而不是所谓的父辈。
这是很值得思考的问题,还是去读教材中的那个巩固练习中提到的网页吧。