您的位置:首页 > 编程语言 > Python开发

Python3萌新入门笔记(28)

2018-02-02 15:37 423 查看
这一篇教程是关于类的最后一部分内容。

八、多继承(Multiple Inheritance)

注意:不要和多重继承搞混,多重继承是指C继承B,B继承A这样的继承形式。

示例代码:(多重继承)
class A:
pass
class B(A):
pass
class C(B):
pass


多继承是指类能够继承自多个超类。

所以,在上一篇教程我们在使用__bases__特性时,能够看到bases是一个复数。

多继承的使用很简单,只需要在来名称后面的括号中写入超类的名称并用逗号分隔即可。

示例代码:(多继承)
class A:
pass
class B:
pass
class C(A,B):
pass


不过要注意,当多个超类都具有相同的特性时,只会继承第一个(最左侧)超类中的特性。

在现实生活中,有很多这种情况,例如小学生既是学生又是儿童。

就像下面这段代码。

示例代码:
class Children:  # 创建儿童类
age = 10

def activitie(self):  # 定义活动方法
print('我周末去儿童游乐园玩!')

class Student:  # 创建学生类
grade = 3

def activitie(self):  # 定义活动方法
print('我每天放学在家写作业!')

class Pupil(Children, Student):  # 创建小学生类
def __init__(self):
print('我今年%d岁,已经上%d年级啦!' % (self.age, self.grade))

p = Pupil()  # 显示输出结果为:我今年10岁,已经上3年级啦!
p.activitie()  # 显示输出结果为:我周末去儿童游乐园玩!


九、检查对象的特性

如果想知道一个对象是否具有某个特性,可以使用hasattr(o,name)函数,当包含指定特性的名称时,返回值为True;否则,为False。

借用上面的学生类,我们进行特性的检查。
c = Children()
print(hasattr(c, 'age'))  # 检查特性age,显示输出结果为:True
print(hasattr(c, 'grade'))  # 检查特性grate,显示输出结果为:False
print(hasattr(c, 'activitie'))  # 检查方法activitie,显示输出结果为:True
print(hasattr(c, 'study'))  # 检查方法study,显示输出结果为:False


另外,我们还可以检查一个对象的特性是否能被调用。

我们可以使用getattr(o,name,default)获取对象的特性,然后通过callable(object)检查。
print(callable(getattr(c, 'activitie', None)))  # 显示输出结果为:True
print(callable(getattr(c, 'study', None)))  # 显示输出结果为:False


上方代码中,我们为getattr()函数指定了默认值None,这样当找不到特性时,返回值为False。

如果不设置默认值None,则会抛出异常。

AttributeError: ‘Children’ object has no attribute ‘study’

特性错误: ‘Children’ 对象不包含 ‘study’特性。

十、多态(Polymorphic)

多态的字面意思是多种形式。

在Python中是指多个不同类的对象,都具有一些共同的特性,这些对象中的任何一个对象,都可以调用这些共同的特性。但是,因为是不同类的对象,所以,在调用同一个特性时,会表现出不同的行为。

这里提到的对象允许外部访问的共同特性,也就是在前面我们提到过接口。

当我们处理多态对象时,只需要关心它所提供的接口。

例如,count()方法就是多态特性。

示例代码:
obj = '小楼棒,小楼帅,小楼好厉害!'  # 变量引用字符串对象
print(obj.count('小楼'))  # 显示输出结果为:3
obj = ('小楼', '樱井', '小楼', '明步')  # 变量引用元组对象
print(obj.count('小楼'))  # 显示输出结果为:2


在上方代码中,“obj”就是多态对象,它可以是不同的对象。

我们不管“obj”是什么对象(字符串或元组或其它),只需要关心它的接口中有没有count()这个方法。

如果有count()这个方法,就能够对对象进行处理。

但是,虽然调用的方法都是同一个名称,因为处理的是不同的对象,实际上具体的处理行为是不一样的。

 

接下来,我引用一个其它编程语言中的示例,来帮助大家了解多态。

动物园的饲养员(Feeder ),能够喂养狮子(Lion),老虎(Tiger)和狗熊(Bear)。

饲养员要对这些动物进行喂食的操作。

假设我们不做多态处理。

示例代码:(非多态)
# 定义动物
class Lion:  # 定义狮子类
def lion_eat(self):  # 定义进食函数
print('狮子在吃东西!')

class Tiger:  # 定义老虎类
def tiger_eat(self):  # 定义进食函数
print('老虎在吃东西!')

class Bear:  # 定义狗熊类
def bear_eat(self):  # 定义进食函数
print('狗熊在吃东西!')
# 定义饲养员
class Feeder:
def feed_lion(self, lion):  # 定义喂养狮子的函数
lion.lion_eat()

def feed_tiger(self, tiger): # 定义喂养老虎的函数
tiger.tiger_eat()

def feed_bear(self, bear): # 定义喂养猴子的函数
bear.bear_eat()

# 喂养过程
feeder = Feeder()
lion = Lion()
feeder.feed_lion(lion)  # 显示输出结果为:狮子在吃东西!
tiger = Tiger()
feeder.feed_tiger(tiger)  # 显示输出结果为:老虎在吃东西!
bear = Bear()
feeder.feed_bear(bear)  # 显示输出结果为:狗熊在吃东西!


上方的代码虽然运行正常,但是如果给饲养员增加工作量,让他再多喂一只猴子。

我们就需要继续增加一些代码。

示例代码:(增加的代码)
#定义动物
class Monkey:
def monkey_eat(self):
print('猴子在吃东西!')

#定义饲养员
class Feeder:
def feed_monkey(self, monkey):
monke.monkey_eat()

# 喂养过程
monkey = Monkey()
feeder.feed_monkey(monkey)


很显然,每增加一个喂养一个动物,我们都要增加这么多代码。

那么,通过多态处理呢?

示例代码:(多态)
class Lion:  # 定义狮子类
def eat(self):  # 定义进食函数
print('狮子在吃东西!')

class Tiger:  # 定义老虎类
def eat(self):  # 定义进食函数
print('老虎在吃东西!')

class Bear:  # 定义狗熊类
def eat(self):  # 定义进食函数
print('狗熊在吃东西!')

class Feeder:  # 定义饲养员类
def feed_animal(self, animal):  # 定义喂食方法
animal.eat()

# 喂养过程
feeder = Feeder()
animal = Lion()
feeder.feed_animal(animal)  # 显示输出结果为:我是狮子,在吃东西!
animal = Tiger()
feeder.feed_animal(animal)  # 显示输出结果为:我是狮子,在吃东西!
animal = Bear()
feeder.feed_animal(animal)  # 显示输出结果为:我是狗熊,在吃东西!


在上方代码中,每一个动物的进食方法都采用了相同的名称,喂食方法只保留了一个。

并且,喂养过程中调用的喂食方法都是相同的。(因为喂食方法就一个)

这样,多个类中都有一个相同的特性(eat函数),实例对象也就具有了这个相同的特性(eat方法),所以,不管调用的时候是哪一种实例对象(变量animal),都可以调用这个特性(eat方法),但是因为调用这个特性的实例对象(动物)不同,所以产生的行为(eat方法的处理过程)是不同的。

这就是多态。

那么,对比之前未做多态处理的代码,有什么好处呢?

当同样需要增加喂养猴子时,通过多态处理的代码,只需要增加新的动物种类,以及喂养过程中对动物的实例化和调用喂养方法。

示例代码:(增加部分)
#定义动物
class Monkey:
def eat(self):
print('猴子在吃东西!')

# 喂养过程
animal = Monkey()
feeder.feed_animal(animal)


从这个示例我们也能够看出,喂食方法无需再重复定义,多喂养一种动物只需要定义一个新的类。

这也就说明了,多态能够提高代码的复用性,让代码更加精简易读,并且降低了代码的耦合度(紧密配合与相互影响的程度),提升了代码的扩展性。

另外,值得注意的是,Python中多态的概念不同于其它编程语言,在大多编程语言中,如果需要进行多态处理,会要求具有相同特性的类(例如上方代码中的狮子类、老虎类等)必须继承自同一个超类(需要定义Animal类),这样在调用特性时是通过超类寻找相应的子类。

而Python中无需这么做,就像上方的代码,我们并没有定义一个动物的超类,让动物的子类去继承这个超类。

所以,严格来说Python中没有多态这个概念,因为Python自身就是多态的语言。

本节知识点:

1、多继承

2、检查对象的特性

3、多态

本节英文单词与中文释义:

1、multiple:多个/多重

2、base:基本

3、children:儿童

4、age:年龄

5、grade:年级

6、pupil:小学生

7、activitie:活动

8、polymorphic:多态

9、animal:动物

10、lion:狮

11、tiger:虎

12、bear:熊

13、monkey:猴

14、eat:吃

15、feed:喂养

16、feeder:饲养员

转载自:魔力
• Python » Python3萌新入门笔记(28)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息