**
一、继承特性
**
1、什么是继承
继承就是让类和类之间产生父子关系,子类可以拥有父类的静态属性和方法。
[继承就是可以获取另外一个类中的静态属性和普通方法。(并非所有成员)]
在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类。(python中的继承分为:单继承和多继承)
2、继承中的子类和父类的概念
父类:用于被继承的类,称之为父类,也叫做基类,或者超类。
子类:继承其他类的类,称之为子类,也叫做派生类。
3、继承的作用
就是提高代码的重用率
**例1、**定义一个父类Animal,将Cat和Dog类中的相同功能抽取到Animal中
#父类
class Animal(object):
type = '动物'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('吃...')
def sleep(self):
print('睡觉')
#子类
class Dog(Animal):
def look_house(self):
print('看大门...')
#子类
class Cat(Animal):
def climb_tree(self):
print('爬树...')
dog = Dog('哈士奇', 8)
dog.eat()#调用父类的方法
dog.sleep()
dog.look_house()
print(dog.type)
cat = Cat('橘猫', 10)
cat.eat()
cat.sleep()#调用父类的方法
cat.climb_tree()
查看继承的父类
格式:类名__bases__
print(Cat.__bases__)
print(Dog.__bases__)
print(Animal.__bases__)
注意:
(1)python3中如果一个类没有继承任何类,默认继承object类。我们管这种类叫做新式类。
(2)object类,可以说是python中的祖宗,所有的类都是从object类中继承下来的。
4、方法的复写
子类中定义了和父类中相同的方法,我们叫做方法的复写(派生方法)。实例对象调用此方法的时候就会调用自己类中的方法了。
什么时候使用方法的复写:当父类的方法不能满足子类的需求的时候,就可以使用方法的复写。
例1、
class Animal(object):
type = '动物'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('吃。。。')
def sleep(self):
print('睡。。。')
class Dog(Animal):
def look_house(self):
print('看大门...')
def eat(self):
print('吃狗粮...')
def sleep(self):
print('睡觉轻...')
dog = Dog('二哈', 8)
dog.eat()
dog.sleep()
5、super()
当子类和父类有相同的方法的时候,子类默认会调用自己的方法,而不能使用父类的方法。如果想使用父类的方法,我们就可以使用super()方法来调用父类的方法
1.super(类名,对象名).方法()既可以在类的内部也可以在类的外部使用。
2.父类类名.方法名(self)–>Animal.eat(self) 既可以在内部也可也在外部使用
3.super().eat()–> 只能在类的内部。
class Animal(object):
type = '动物'
def eat(self):
print('吃...')
def sleep(self):
print('睡觉')
class Dog(Animal):
def look_house(self):
print('看大门...')
def eat(self):
# super().eat() # 调用的是父类的eat()方法。
# Animal.eat(self) # 父类类名.方法名(self)
print('吃狗粮...')
dog = Dog()
super(Dog, dog).eat() # super(类名,对象名).方法()
6、init()方法
1.如果子类不复写__init__()方法,会自动调用父类的__init__()方法。
2.如果子类复写了__init__()方法,不会自动调用父类的__init__()方法。
(不推荐使用这种方式)
3. 推荐显示的调用父类的方法。super().init()
class Person(object):
def __init__(self):
print('person...')
class Student(Person):
def __init__(self):
super().__init__()
print('student...')
student = Student()
注意:
存在隐患,例如父类的初始化方法有参数,子类初始化无参数,子类再调用父类的参数的时候就会报错。
7、派生属性
派生属性: 子类中添加的新属性
属性的覆盖:子类和父类有相同的属性的时候,将调用自己类中的属性
class Person(object):
num = 10
def __init__(self, name):
print('person...')
class Student(Person):
num = 20
def __init__(self, name, age): # age是派生属性
super().__init__(name)
self.name = name
self.age = age
print('student...')
def eat(self):
print(super().num)#通过super()调用父类的方法
print('xxx')
student = Student('zs', 10)
print(student.age)
student.eat()
print(Student.num)#调用自己类中的属性
8、私有属性私有方法在继承中的表现
class Person(object):
num = 10
__num1 = 20
def __test1(self):
print('__test1...')
class Student(Person):
def test(self):
print(Student.num)#可继承下来
# print(Student.__num1) # 不能被继承下来
def test3(self):
print('test3...')
# self.__test1() # 父类的私有方法是不能被继承下来的。
student = Student()
student.test3()#可继承下来
9、抽象类
之前我们定义了Person类实现了eat()、drink()方法,每种人都会吃喝,但是吃喝的地点不同,如果实现了方法体就浪费了。因此我们可以只定义eat()方法,不实现方法体,这种形式我们可以将方法定义为抽象方法,具有抽象方法的类就叫做抽象类。
抽象类是一个特殊的类,只能被继承,不能实例化,抽象类中可以有抽象方法和普通方法。
1)定义抽象类需要导入 abc模块。from abc import ABCMeta, abstractmethod
2)抽象方法:只定义方法,不具体实现方法体。
在定义抽象方法时需要在前面加入:@abstractmethod
抽象方法不包含任何可实现的代码,因此其函数体通常使用pass。
from abc import ABCMeta, abstractmethod
# 抽象类
class Animal(metaclass=ABCMeta):
# 抽象方法
@abstractmethod
def eat(self): pass
@abstractmethod
def sleep(self): pass
# 可以定义普通的方法。
def play(self):
print('拆家')
class Dog(Animal):
def eat(self):#必须调用父类中的抽象方法
print('吃狗粮...')
def sleep(self):#必须调用父类中的抽象方法
print('轻轻的睡觉')
dog = Dog()
dog.play()
注意:子类继承了抽象类父类,子类必须实现父类的抽象方法。
**
二、多继承
**
一个子类可以继承多个父类,就是多继承,并且拥有所有父类的属性和方法。
1、语法
class 子类名(父类名1,父类名2…) : pass
class A(object):
num_a = 10
def test1(self):
print('A test1')
class B(object):
num_b = 20
def test2(self):
print('B test2')
class C(A, B):
pass
c=C
c.test1()
c.test2()
**2、**如果子类和父类有相同的方法,就会调用子类中的方法。如果不同的父类中存在着相同的方法名称,子类对象调用的时候会调用哪个父类中的方法呢? Python会根据 MRO(method resolution order) 方法解析顺序列表进行查找。
c = C()
c.test1()
print(C.mro()) # 使用 mro()方法 来查看类的搜索路径
print(C.__mro__)
3、继承原理
1)子类会先于父类被检查
2)多个父类会根据它们在列表中的顺序被检查
3)如果对下一个类存在两个合法的选择,选择第一个父类
4、多继承中super本质
不是直接查找父类,而是根据调用节点的广度优先顺序执行的。
与调用顺序刚好相反
三、多态特性
多态就是不同子类对象调用父类的方法产生不同的结果。
**例1、**使用不同支付工具给商店支付钱
import abc
class Pay(metaclass=abc.ABCMeta):#抽象类
#抽象方法
@abc.abstractmethod
def pay(self, money): pass
class Alipay(Pay):
def pay(self, money):
print('支付宝到账{}元'.format(money))
class ApplePay(Pay):
def pay(self, money):
print('苹果支付{}元'.format(money))
class Person(object):
def consumption(self, pay, money):#消费
pay.pay(money)
alipay = Alipay()
apple_pay = ApplePay()
person = Person()
person.consumption(alipay,150)
person.consumption(apple_pay, 200)
例2、
from abc import ABCMeta, abstractmethod
class File(metaclass=ABCMeta):
@abstractmethod
def read(self): pass
@abstractmethod
def write(self): pass
class Word(File):
def read(self):
print('很优雅的读...')
def write(self):
print('很优雅的写...')
class Txt(File):
def read(self):
print('很大声的读...')
def write(self):
print('很夸张的写...')