面向对象的编程带来的主要好处之一是代码的重用,实现各种重用的方法之一是通过继承机制。继承完全可以理解成类之间的父类和子类型关系。
继承概念:继承是类与类的一种关系,是一种子类与父类的关系,即爸爸与儿子,爸爸生个儿子,儿子继承爸爸的属性和方法。
如猫类,猫是动物;猫类继承于动物类,动物类为父类也是所有动物的基类;猫类是动物类的子类,也是动物类的派生类。
Python有单继承与多继承。单继承即子类继承于一个类,多继承即子类继承于多个类,多继承会比较少遇到,本章节主要讲单继承。
什么时候使用继承:假如我需要定义几个类,而类与类之间有一些公共的属性和方法,这时我就可以把相同的属性和方法作为基类的成员,而特殊的方法及属性则在本类中定义。这样子类只需要继承基类(父类),子类就可以访问到基类(父类)的属性和方法了,它提高了代码的可扩展性和重用行。
如:猫,狗 都属于动物,它们行为相似性高,都会叫,会吃,会喝,会拉,会撒娇。
如下定义一个动物类Animal为基类,它基本两个实例属性name和age、一个方法call。
class Animal(object): # python3中所有类都可以继承于object基类
def __init__(self, name, age):
self.name = name
self.age = age
def call(self):
print(self.name, '会叫')
######
# 现在我们需要定义一个Cat 猫类继承于Animal,猫类比动物类多一个sex属性。
######
class Cat(Animal):
def __init__(self,name,age,sex):
super(Cat, self).__init__(name,age) # 不要忘记从Animal类引入属性
self.sex=sex
if __name__ == '__main__': # 单模块被引用时下面代码不会受影响,用于调试
c = Cat('喵喵', 2, '男') # Cat继承了父类Animal的属性
c.call() # 输出 喵喵 会叫 ,Cat继承了父类Animal的方法
注意:一定要用 super(Cat, self).init(name,age) 去初始化父类,否则,继承自 Animal的
Cat子类将没有 name和age两个属性。 函数super(Cat, self)将返回当前类继承的父类,即
Animal,然后调用__init__()方法,注意self参数已在super()中传入,在__init__()中将隐式传递,不能再写出self。
上面例子中 Animal 的子类 Cat 继承了父类的属性和方法,但是我们猫类 Cat 有自己的叫声 ‘喵喵’ ,这时我们可以对父类的 Call() 方法进行重构。如下:
class Cat(Animal):
def __init__(self, name, age, sex):
super(Cat, self).__init__(name,age)
self.sex = sex
def call(self):
print(self.name,'会“喵喵”叫')
if __name__ == '__main__':
c = Cat('喵喵', 2, '男')
c.call() # 输出:喵喵 会“喵喵”叫
类方法的调用顺序,当我们在子类中重构父类的方法后,Cat子类的实例先会在自己的类 Cat 中查找该方法,当找不到该方法时才会去父类
Animal 中查找对应的方法。
class Animal(object):
pass
class Cat(Animal):
pass
A= Animal()
C = Cat()
子类与父类的关系是 “is” 的关系,如上 Cat 继承于 Animal 类,我们可以说:
“A”是 Animal 类的实例,但,“A”不是 Cat 类的实例。
“C”是 Animal 类的实例,“C”也是 Cat 类的实例。
判断对象之间的关系,我们可以通过 isinstance (变量,类型) 来进行判断:
print('"A" IS Animal?', isinstance(A, Animal))
print('"A" IS Cat?', isinstance(A, Cat))
print('"C" IS Animal?', isinstance(C, Animal))
print('"C" IS Cat?', isinstance(C, Cat))
输出结果:
"A" IS Animal? True
"A" IS Cat? False
"C" IS Animal? True
"C" IS Cat? True
拓展:isinstance() 判断变量类型
函数 isinstance() 不止可以用在我们自定义的类,也可以判断一个变量的类型,如判断数据类型是否为 int、str、list、dict 等。
print(isinstance(100, int))
print(isinstance('100', int))
print(isinstance(100, str))
print(isinstance('100', str))
输出:
True
False
False
True
类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Animal 派生出 Cat和 Dog,并都写了一个 call() 方法,如下示例:
class Animal(object):
def __init__(self, name, age):
self.name = name
self.age = age
def call(self):
print(self.name, '会叫')
class Cat(Animal):
def __init__(self, name, age, sex):
super(Cat, self).__init__(name, age)
self.sex = sex
def call(self):
print(self.name, '会“喵喵”叫')
class Dog(Animal):
def __init__(self, name, age, sex):
super(Dog, self).__init__(name, age)
self.sex = sex
def call(self):
print(self.name, '会“汪汪”叫')
我们定义一个 do 函数,接收一个变量 ‘all’,如下:
def do(all):
all.call()
A = Animal('小黑',4)
C = Cat('喵喵', 2, '男')
D = Dog('旺财', 5, '女')
for x in (A,C,D):
do(x)
输出结果:
小黑 会叫
喵喵 会“喵喵”叫
旺财 会“汪汪”叫
小知识:多态
这种行为称为多态。也就是说,方法调用将作用在 all 的实际类型上。C 是 Cat 类型,它实际上拥有自己的 call() 方法以及从 Animal 继承的 call 方法,但调用 C .call() 总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。
传递给函数 do(all) 的参数 all 不一定是 Animal 或 Animal 的子类型。任何数据类型的实例都可以,只要它有一个 call() 的方法即可。其他类不继承于 Animal,具备 call 方法也可以使用 do 函数。这就是动态语言,动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。
在学习python中有任何困难不懂的可以微信扫描下方CSDN官方认证二维码加入python交流学习
多多交流问题,互帮互助,这里有不错的学习教程和开发工具。
(这里每天都会不定时更新python不同题型和教程,希望大家一起学习,一起进步)
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
检查学习结果。
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
最后,千万别辜负自己当时开始的一腔热血,一起变强大变优秀。