笨办法学python3进阶篇pdf,笨办法学python第三版

大家好,给大家分享一下笨办法学python 3电子书下载,很多人还不知道这一点。下面详细解释一下。现在让我们来看看!

Source code download: 本文相关源码

练习44 继承和组合

永远记住这一点:继承的大多数用法都可以用组合(composition)来简化或替换。并且无论如何都要避免多重继承python自学可行吗

内容提要:

1. 什么是继承?
(1)隐式继承
(2)显示继承
(3)改变前后
(4)三种组合
(5)为何用super()
(6)组合
2. 何时使用继承和组合

什么是继承?

继承用来表明一个类将从其父类那里获得大多数或所有特性。当你在做这种专门化时,有三种父类和子类可以交互的方法:
(1)对子类的行为意味着对父类的行为。——隐式继承
(2)子类上的操作会覆盖父类上的操作。——显示继承
(3)子类上的操作会更改父类上的操作。

1、隐式继承

代码:ex44a.py

class Parent(object): #创建父类

    def implicit(self): #创建函数
        print("PARENT implicit()")

class Child(Parent): #创建子类Child,继承至父类Parent
    pass

dad = Parent() #Parent()类实例化
son = Child() #Child()类实例化

dad.implicit() #调用父类内部函数
son.implicit() #调用函数继承至父类

输出结果:

PARENT implicit()
PARENT implicit()

说明:
pass关键词:“暂时跳过”,pass 是一种空操作,解释器执行到它的时候,除了检查语法是否合法,什么也不做就直接跳过。使用在函数、类、循环体或者条件判断语句中。用于补充语法的完整性,要不然代码会报错。

Child()的类底下使用pass空块,没有定义实际内容,但它仍旧可以可以调用函数implicit(),就是因为它继承了父类Parent()的函数,这就是隐式继承。因此如果将函数放在父类中(比如 Parent),然后所有子类(比如 Child)会自动获得这些特性。对于需要写很多重复代码的类来说非常方便。

2、显式继承

代码:ex44b.py

#显式继承——子类中定义一个与父类同名的函数,以替换父类中的函数功能
class Parent(): #创建父类

    def override(self): #创建父类的函数
        print("Parent override()")

class Child(Parent): #创建子类Child继承至父类Parent

    def override(self): #创建与父类中函数同名的函数,但功能与其不同
        print("Child override()")

dad = Parent() #实例化父类
son = Child() #实例化子类

dad.override() #调用父类中的函数override()
son.override() #调用子类中的函数override()

输出结果:

Parent override()
Child override()

说明:
隐式调用函数的问题在于,有时希望子类与父类的行为有所不同。**只需要在子类( Child) 中定义一个与父类(Parent)同名函数,子类上的操作会覆盖父类上的操作。**如上代码中,父类与子类都同时存在的override()函数,运行之后的结果不同。

3、修改前后

代码:ex44c.py

#子类上的操作会更改父类上的操作
#修改类中函数前后
class Parent(): #创建父类

    def altered(self): #创建父类函数
        print("Parent altered()")

class Child(Parent): #创建子类

    def altered(self): #创建与父类函数同名的子类函数,覆盖父类函数
        print("Child, Before Parent altered()") #打印
        super().altered() #利用super(超类)调用父类中的函数
        print("Child, After Parent altered()") #继续打印

dad = Parent() #实例化父类
son = Child() #实例化子类

dad.altered() #调用父类函数
son.altered() #调用子类函数

输出结果:

Parent altered()
Child, Before Parent altered()
Parent altered()
Child, After Parent altered()

说明:
第三种使用继承的方式是覆盖的一种特殊情况,可以在父类版本运行前后更改子类的函数内容。首先,与之前一样在子类中创建一个与父类同名的函数,覆盖原先的函数;其次使用super()函数调用父类中的函数。

4、以上三中继承形式结合

过一遍这段代码的每一行,并每一行加上注释,说明它的作用。

#三者结合
class Parent(): #创建父类
    
    def override(self): #创建父类函数override
        print("Parent override()") #函数的行为,打印字符串

    def implicit(self): #创建父类函数implicit()
        print("Parent implicit()") #函数的行为,打印字符串

    def altered(self): #创建父类函数altered()
        print("Parent altered()") #函数的行为,打印字符串

class Child(Parent): #创建子类
    def override(self): #创建与父类中override同名的函数,覆盖父类中该函数的内容
        print("Child override()")

    def altered(self): #创建与父类中altered同名函数,覆盖父类该函数内容
        print("Child, Before Parent altered()")
        super().altered() #调用函数super(超类),再次继承父类中的函数altered()
        print("Child, After Parent altered()")

dad = Parent() #父类实例化
son = Child() #子类实例化

dad.implicit() #调用父类函数implicit()
son.implicit() #子类中未定义函数implicit(),但隐式继承了父类,也可调用该函数,且内容相同

dad.override() #调用父类override()函数
son.override() #调用子类override()函数

dad.altered() #调用父类altered()函数
son.altered() #调用子类altered()函数

输出结果:

Parent implicit()
Parent implicit()
Parent override()
Child override()
Parent altered()
Child, Before Parent altered()
Parent altered()
Child, After Parent altered()
5、用super()的理由

什么是多重继承?(之前练习有学习了解)
如下代码:

class SuperFun(Child, BadStuff):
pass

如上代码中创建的类SuperFun(),同时继承自Child()和BadStuff()两个类,即一个类继承了一个或多个类就是“多重继承”。
在出现多重继承的情况下,对任何 SuperFun 的实例执行隐式操作时,Python 都必须在 Child 类和 BadStuff 类的层级结构中查找可能的函数,不过它需要以一致的顺序来执行这项操作。为了做到这一点,Python 使用了“方法解析顺序”(method resolution order,MRO)和一种被称为 C3 的算法,这种算法很复杂,因此使用super()函数可以帮助我们在需要修改的地方进行处理即可。

用__init__来使用super()
super() 最常用的用法其实是在子类中使用基类的 init 函数。这通常是你在一个子类中唯一需要做一些操作,然后在父类中完成初始化的地方。
示例如下:

class Child(Parent):

	def __init__(self, stuff): #初始化函数
		self.stuff = stuff
		super(Child,self).__init__() #调用父类的初始化函数
6、组合

继承很有用,但是还有一种能实现相同效果的方法,就是使用其他类和模块,而不是依赖于隐式继承。当使用继承时,子类中存在大量的编写新代码来替换或者更改函数功能的时候,可以通过调用模块中的函数来实现。示例如下:

代码ex44e.py

class Other(): #创建一个额外的类Other()

    def override(self):  #创建函数
        print("Other override()")
    
    def implicit(self): #创建类的函数
        print("Other implicit()")

    def altered(self): #创建类的函数
        print("Other altered()")

class Child(): #创建类Child()

    # def __init__(self): #创建初始化函数
    #创建Other()类与Child()之间的桥梁,也可以没有,但是调用Other()类中的函数方式会有所不用
    #     self.other = Other() 

    def implicit(self): #创建函数implicit()
        # self.other.implicit() #对应第一种,调用Other()类中的implicit()函数
        Other().implicit() #对应第二种,调用Other()类中的implicit()函数

    def override(self): #创建函数override()
        print("Child override()")

    def altered(self): #创建altered()函数
        print("Child, Before Other altered()")
        # self.other.altered() #第一种,调用Other()类中的altered()函数
        Other().altered() #第二种,调用Other()类中的函数altered()
        print("Child, After Other altered()")

son = Child() #实例化Child类

son.implicit() #调用函数implicit()
son.override() #调用函数override()
son.altered() #调用函数altered()

输出结果:

Other implicit()
Child override()
Child, Before Other altered()
Other altered()
Child, After Other altered()

说明:
可以看到,Child 和 Other 中的大多数代码都是相同的,可以完成相同的事情。唯一的区别是必须定义一个 Child.implicit 函数来完成这个动作。
其中在Child()类中调用Other()类的方法有两种。
第一种,在Child类的__init__函数中定义other属性,self.other = Other(),后续可直接使用self.other.函数名来调用Other类中的函数。
第二种,直接在Child类中,实例化Other类后调用,例如:Other().implicit()

问题:是否可以将Other类放入Other.py的模块中,去调用它?

可以,代码如下:

文件:other.py

class Other(): #创建一个额外的类Other()

    def override(self):  #创建函数
        print("Other override()")
    
    def implicit(self): #创建类的函数
        print("Other implicit()")

    def altered(self): #创建类的函数
        print("Other altered()")

文件:ex44_Child.py

from other import Other #从模块Other中调用Other类

class Child(): #创建类Child()

    def __init__(self): #创建初始化函数
    #创建Other()类与Child()之间的桥梁,也可以没有,但是调用Other()类中的函数方式会有所不用
        self.other = Other() 

    def implicit(self): #创建函数implicit()
        self.other.implicit() #对应第一种,调用Other()类中的implicit()函数
        # Other().implicit() #对应第二种,调用Other()类中的implicit()函数

    def override(self): #创建函数override()
        print("Child override()")

    def altered(self): #创建altered()函数
        print("Child, Before Other altered()")
        self.other.altered() #第一种,调用Other()类中的altered()函数
        # Other().altered() #第二种,调用Other()类中的函数altered()
        print("Child, After Other altered()")

son = Child() #实例化Child类

son.implicit() #调用函数implicit()
son.override() #调用函数override()
son.altered() #调用函数altered()

输出结果:

Other implicit()
Child override()
Child, Before Other altered()
Other altered()
Child, After Other altered()

说明:
可以通过other.py文件调用Other类,只需要在ex44_Child.py 文件的脚本代码中加入import调用模块,即from other import Other。在Child类中的调用方式与之前完全相同。

7、何时使用继承和组合

“继承与组合”的问题可以归结为试图解决可复用代码的问题。
——继承通过在父类中创建隐含相同功能的函数的机制来解决这个问题。
——组合通过提供模块以及调用其他类中的函数来解决这个问题。

三个指导方针(建议,但可能无法遵守):
1、无论如何都要避免多重继承,因为它太复杂而且不可靠。
2、使用组合将代码打包到模块中,这些模块可以用于许多不同的、不相关的地方和情境。
3、代码的可复用部分之间有清楚的关联(很明显的父类与子类关系,如动物和猫)或者必须要用继承时,用继承。

附加练习

阅读 : http://www.python.org/dev/peps/pep-0008/ 文件(该网站需要翻墙)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值