类的三大特性-继承

day 22

面向对象之继承:

一、继承简述:

1、继承的定义:

继承描述的是一种类与类之间的关系,即子类与父类的关系。

继承是一种创建新式类的方式,新建的类可以继承一个或多个父类(Python支持多继承),父类又称为超类或基类,新建的类则称为派生类或者子类。

##新式类与经典类的区分:
首先:新式类指的是直接或间接的继承了object类的类。
1.只有在python2中才分新式类和经典类,python3中统一都是新式类
2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类
3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类
3.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类

 


2、继承的特性:

子类会“遗传”父类的属性,这种特性决定了它解决代码冗余的特点。

# python中的单继承与多继承
class ParentClass1: #定义父类
    passclass ParentClass2: #定义父类
    passclass SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
    passclass SubClass2(ParentClass1,ParentClass2): #python支持多继承,多个父类之间用逗号分隔开
    pass#--》查看继承结果:
>>> SubClass1.__bases__ #(查看继承结果的方法)#__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
(<class '__main__.ParentClass1'>,)
>>> SubClass2.__bases__
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

 

3、抽象

前面叙述继承是一种类与类之间的关系,要找出这种关系就必须先抽象。

抽象:此处是指抽取对象之间比较相似或者比较像的部分。

抽象分为两个层次:

a、抽取对像与对象之间相似的部分,从而定义出类。

b、从两个类中在抽取出相似的部分,从而有了父类。

注:抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类。

#通过抽取提取对象中的相似部分得到类,在通过提取类与类之间相似的部分得到父类
==========================第一部分
例如
​
  猫可以:喵喵叫、吃、喝、拉、撒
​
  狗可以:汪汪叫、吃、喝、拉、撒
​
如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,伪代码如下:
 
​
#猫和狗有大量相同的内容
class 猫:
​
    def 喵喵叫(self):
        print '喵喵叫'def 吃(self):
        # do something
def 喝(self):
        # do something
def 拉(self):
        # do something
def 撒(self):
        # do something
class 狗:
​
    def 汪汪叫(self):
        print '喵喵叫'def 吃(self):
        # do something
def 喝(self):
        # do something
def 拉(self):
        # do something
def 撒(self):
        # do something
​
​
​
==========================第二部分
上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。如果使用 继承 的思想,如下实现:
​
  动物:吃、喝、拉、撒
​
     猫:喵喵叫(猫继承动物的功能)
​
     狗:汪汪叫(狗继承动物的功能)
​
伪代码如下:
class 动物:
​
    def 吃(self):
        # do something
def 喝(self):
        # do something
def 拉(self):
        # do something
def 撒(self):
        # do something
# 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
class 猫(动物):
​
    def 喵喵叫(self):
        print '喵喵叫'
        
# 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
class 狗(动物):
​
    def 汪汪叫(self):
        print '喵喵叫'
​
​
​
​
==========================第三部分
#继承的代码实现
class Animal:
​
    def eat(self):
        print("%s 吃 " %self.name)
​
    def drink(self):
        print ("%s 喝 " %self.name)
​
    def shit(self):
        print ("%s 拉 " %self.name)
​
    def pee(self):
        print ("%s 撒 " %self.name)
​
​
class Cat(Animal):
​
    def __init__(self, name):
        self.name = name
        self.breed = ''def cry(self):
        print('喵喵叫')
​
class Dog(Animal):
​
    def __init__(self, name):
        self.name = name
        self.breed=''def cry(self):
        print('汪汪叫')
​
​
# ######### 执行 #########
​
c1 = Cat('小白家的小黑猫')
c1.eat()
​
c2 = Cat('小黑的小白猫')
c2.drink()
​
d1 = Dog('胖子家的小瘦狗')
d1.eat()
View Code

 

4、派生

派生指的是子类继承某个父类的所有属性,并且还拥有自己独有的属性或技能,此种子类则称之为派生类。(即子类中出现了任何新内容,则此子类就是一个派生类)

class People:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
​
    def sayHI(self):
        print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))
​
​
# Test不能称为派生类 , 因为没与任何独特的内容与父类完全一致
class Test(People):
    pass# 派生类属于子类吗?   派生类一定是某个子类,但是子类不一定是派生类
# Student类就称为 Person类的派生类
class Student(People):
    def __init__(self,name,age,sex,number):
        super().__init__(name,age,sex)
        self.number = number
    # 上课
    def take_class(self):
        print("%s 正在上课.....")

 

5、子类访问父类中属性的方法

#########父类#########
class People:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
        print(self)
​
    def sayHI(self):
        print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))
​
class Student(People):
    def __init__(self,name,age,sex,number):
        #子类访问父类的方式一:(指名道姓的进行调用)
        People.__init__(self,name,age,sex)
        # 子类中重用父类种方法的方式二
        # super() # 表示创建一个特殊的对象 用于调用父类的方法
        # super().__init__(name,age,sex)
        # 了解:在python2中 super的使用方式有所不同 需要传入当前类,当前对象
        #super(Student,self).__init__(name,age,sex)
        self.number = number
​
    # 上课
    def take_class(self):
        print("%s 正在上课.....")
​
stu1 = Student("阿三",20,"woman","9527")
print(stu1)
print(stu1.name,stu1.age,stu1.sex)

 

6、属性查找:

class Foo:
    def f1(self):
        print('Foo.f1')
​
    def f2(self):
        print('Foo.f2')
        self.f1()
​
class Bar(Foo):
    def f1(self):
        print('Bar.f1')
​
b=Bar()
b.f2()
​
#result:Foo.f2
#        Bar.f1
#注:属性查找遵循的定律始终是现在自己的名称空间中查找属性——》父类。。。最后抛出异常(没找到)
#python中提供了一个查看属性的查找顺序的方法(类名.mro())
class S:
    pass
class Student(S):
    pass# __bases__用于查看父类
print(Student.__bases__)
​
# 显示属性的查找顺序列表,属性查找属性就是按照该列表来查找的
print(Student.mro())

 

注:当继承的多个父类存在共通父类时,会产生菱形继承的关系,此时的查找顺序为先深度优先,再广度优先。

没有菱形继承的关系时,查找顺序会沿着一条路径找到低,如果没有再找其他路径(深度优先)的查找方式进行查找。

posted @ 2018-12-14 20:10  zhao_peng  阅读(754)  评论(0编辑  收藏  举报