作者:mobiledu2502889521 | 来源:互联网 | 2023-08-25 11:52
本文由编程笔记#小编为大家整理,主要介绍了DAY18 面向对象三大特性之继承相关的知识,希望对你有一定的参考价值。
继承
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类。父类又被称为超类,基类;新建的类称为子类或者派生类。
在python3.x版本中,所有的类都默认继承object类。
1.继承与重用
首先,我们来看看一个例子:
# 猫类:吃喝睡,爬树
# 狗类:吃喝睡,看家
#一。通过之前对面向对象的学习,我们可以轻易的定义出这两个类来:
class Cat:
def __init__(self,name,kind,food):
self.name = name
self.kind = kind
self.food = food
def eat(self):
print(‘%s吃%s‘%(self.name,self.food))
def drink(self):
print(‘%s喝水‘%self.name)
def sleep(self):
print(‘%s在睡觉‘%self.name)
def climb(self):
print(‘%s在爬树‘%self.name)
class Dog:
def __init__(self,name,kind,food):
self.name = name
self.kind = kind
self.food = food
def eat(self):
print(‘%s吃%s‘%(self.name,self.food))
def drink(self):
print(‘%s喝水‘%self.name)
def sleep(self):
print(‘%s在睡觉‘%self.name)
def look_after_home(self):
print(‘%s在看家‘%self.name)
但是再往深入探讨,我们会发现其实编写的猫类和狗类代码中,很多都冗余代码。有什么方式能够把重复的代码提取出来吗?当然有,这时候就可以用到继承的思想,父类中的所有属性和方法都可以被子类使用。
#二。把冗余的代码提出来,抽象出一个宠物类,让猫类和狗类都继承这个宠物类。
class Pet:
def __init__(self,name,kind,food):
self.name = name
self.kind = kind
self.food = food
def eat(self):
print(‘%s吃%s‘%(self.name,self.food))
def drink(self):
print(‘%s喝水‘%self.name)
def sleep(self):
print(‘%s在睡觉‘%self.name)
class Cat(Pet):
def climb(self):
print(‘%s在爬树‘%self.name)
class Dog(Pet):
def kanjia(self):
print(‘%s在看家‘%self.name)
tom = Cat(‘Tom‘,‘暹罗猫‘,‘猫粮‘) #子类使用名字(静态变量和方法),如果在子类中没有,就使用父类的
hei = Dog(‘小黑‘,‘二哈‘,‘狗粮‘)
tom.climb()
hei.kanjia()
2.继承与派生
子类也可以定义自己特有的属性或者重新这些属性(但并不会影响到父类),一旦定义了自己的属性且与父类同名时,这种属性称为派生属性。子类的对象调用这个属性时,会直接选择子类中的。
class Pet:
def __init__(self,name,kind,food):
print(‘IN PET‘)
self.name = name
self.kind = kind
self.food = food
def eat(self):
print(‘%s吃%s‘%(self.name,self.food))
def drink(self):
print(‘%s喝水‘%self.name)
def sleep(self):
print(‘%s在睡觉‘%self.name)
class Cat(Pet):
def __init__(self,name,kind,food,eye_color):
print(‘IN CAT‘)
self.eye_color = eye_color #派生属性
# Pet.__init__(name,kind,food)
super().__init__(name,kind,food) #super方法,可以省去self
def climb(self):
print(‘%s在爬树‘%self.name)
class Dog(Pet):
def kanjia(self):
print(‘%s在看家‘%self.name)
tom = Cat(‘阿猫‘,‘橘猫‘,‘猫粮‘,‘绿色‘)
print(tom.eye_color)
# 派生经典考题:
class Foo:
def __init__(self):
self.func()
def func(self):
print(‘in tho foo‘)
class Son(Foo):
def func(self):
print(‘in the son‘)
s1 = Son()
>>>
in the son
################
当self去调用某个方法的时候,不要看self在哪里,而是要明确self代表的到底是谁。
派生总结:
1.当子类中方法要被调用的时候,子类的对象会直接选择子类中的方法。
2.父类的方法不会被自动执行。
3.如果我们既要执行子类的方法又要执行父类中的方法,那么需要在子类的方法中调用父类的方法,有以下两种方法:
(1)父类名.方法名(self,参数...)
(2)super().方法名(参数...) #关于super的查找顺序,请继续往下看。
3.抽象类
抽象类在python中使用的不是特别多,但是在以后的工作中,公司有可能会使用抽象类来制定开发的规则,在以后看源码的过程中,也可能会碰到抽象类的概念。试想一个场景:在今后的多人开发,功能复杂,许多后期拓展功能的项目中,代码的规范变得尤其的重要,而此时,抽象类就能够起到一个很好的模板作用。
抽象类只是一个模板的规范,基本不会实现什么功能,所以抽象类是不可以被实例化的。
#定义抽象类,需要引入一个模块。
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta): #抽象类必须继承一个叫ABCMeta的类
@abstractmethod #抽象类规定的方法,用abstractmethod装饰器装饰,规定了
def pay(self):pass 后面凡是继承该抽象类的子类都必须有一个同名的方法。
class Alipay(Payment):
def pay(self,money):
print(‘使用支付宝支付了%s元‘%money)
4.多继承
在python中允许一个子类是可以继承多个父类的。
class ParentClass1: #定义父类1
pass
class ParentClass2: #定义父类2
pass
class ChildClass(ParentClass1): #定义子类(继承父类1) 单继承
pass
class ChildClass2(ParentClass1,ParentClass2): #多继承
pass
“__base__”:显示子类的一个父类。
“__bases__”:显示子类的所有父类。
5.新式类与经典类
python3.x所有的类都是新式类,所有的新式类都有一个默认继承的父类,叫做object类。
python2.7中经典类和新式类并存。
class Student:Pass #经典类
class Student(object):pass #新式类
总结:
(1)继承了object的类都是新式类。
(2)在py3中所有的类都是新式类。
(3)在py2中既有新式类也有经典类。
一.多继承的顺序/新式类和经典类之间的区别?
(1)钻石继承:广度优先。
新式类的所有多继承关系寻找方法的顺序--->遵循广度优先。
mro()--->显示多继承的继承顺序。
super()--->super方法不是单纯的寻找父类,在多继承中,是遵循mro循序的。
class A:
def func(self):
print(‘A‘)
class B(A):
def func(self):
super().func()
print(‘B‘)
class C(A):
def func(self):
super().func()
print(‘C‘)
class D(B,C):
def func(self):
super().func()
print(‘D‘)
d = D()
d.func()
print(D.mro()) #新式类遵循广度优先。
>>>
A
C
B
D
[, , , , ]
总结:
新式类在多继承时,遵循广度优先。
经典类在多继承时,遵循深度优先。