继承是一种关系,通过继承关系,一个对象可以直接使用另一个对象已定义的方法和属性,描述的是类与类之间的关系

被继承的称之为父类或基类或超类,继承父类的类称之为子类或派生类;

在OOP中 继承描述是类和类之间的关系 例如b类继承a类 b类可以直接使用a类中的属性和方法

用继承的好处:

继承的一方可以直接使用被继承一方已经有的东西 

其目的是为了重用已经有的代码,提高重用性 
如何使用继承

语法:
在类名后面的括号中指定要继承的父类名称
python
class 类名称(父类的名称):
    类的内容 
    
#在python中 一个子类可以同时继承多个父类 

例子:

class Base:
    desc = '这是一个基类'

    def show_info(self):
        print(Base.desc)
    def make_money(self):
        print('一天一个亿')


# 指定父类位Base
class Subclass(Base):
    # def make_money(self):
        pass
        # print('一天一百')

obj = Subclass()
obj.make_money()
print(obj.desc)
View Code

抽象与继承

继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承

继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。

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

class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def say_hi(self):
        print("name:%s,gender:%s,age:%s" % (self.name,self.gender,self.age))


class Teacher(Person):
    def teaching(self):
        print("老师教学生,写代码....")


t1 = Teacher("jack","male",20)
t1.say_hi()


class  Student(Person):
    pass

stu1 = Student("rose","female",18)
stu1.say_hi()
View Code

抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度),每个类之干自己的事情,多个类相同的事情交给父类来干

属性的查找顺序

一个类必然继承另一个类,被继承的类也有可能继承了其他类,相当于C继承B,B又继承A

此时查找属性的顺序是:

对象本身的名称空间 - > 类的名称空间 -> 父类的名称空间 -> 父类的父类名称空间 ->...object类

会沿着继承关系一直往后查找,直到找到为止,由于object是所有类的根类,所以如果找不着最后都会查找object类!

class A:
    text = "haha"

class B(A):
    text = "heihei"
    pass

b = B()
b.text = "xixi"
print(b.text)
class ParentClass1:
    pass

class ParentClass2:
    pass

class SubClass1(ParentClass1):
    pass

class SubClass2(ParentClass1,ParentClass2):
    pass
# __base__只查看从左到右继承的第一个子类,
# __bases__则是查看所有继承的父类
print(SubClass1.__bases__)

print(SubClass2.__bases__)

print(SubClass2.__base__)
View Code

派生与覆盖

派生 当一个类继承自另一个类 并且这个子类拥有与父类不同的内容 就称之为派生

class A:
    def info(self):
        print('hello world')
class B:
    pass

覆盖 (重写) 子类中出现了与父类名称相同的属性 或方法 就会覆盖掉父类的属性或方法

class A:
    text='124'
    def info(self):
        print('hello')

class B(A):
    text='529'
    def info(self):
        print('hello,asedrk')
    pass

b=B()
b.info()
print(b.text)
View Code

练习:

实现一个可以限制元素类型的容器 (字典,列表,元组,集合,字符串)

需求 实现一个能够限制元素类型的列表类

"""
class MyList(list):
    def __init__(self,element_type):
        super().__init__() # 调用父类的初始化方法 来完成基本的初始化
        self.element_type = element_type

    def append(self, object):
        """
        :param object: 是要存储的元素
        :return: 没有
        """
        if type(object) == self.element_type:
            #我们需要在这里访问父类的append函数来完成真正的存储操作
            super(MyList,self).append(object)
        else:
            print("sorry sir, you element type not is %s" % self.element_type)


# 创建是指定要存储的元素类型
m = MyList(int)
# 当你有需求,是需要在创建对象时 干点什么事儿  那就该想到初始化方法

m.append(1)
print(m[0])
m.append("121212")
View Code

子类访问父类的内容

语法

方式1:
super(当前类名称,self).你要调的父类的属性或方法
方式2:
super().你要调的父类的属性或方法
方式3:
类名称.你要调的父类的属性或方法(self)  
#方式3与继承无关 

例子

class Person:
    text='147'
    def __init__(self,name,age,):
        self.name=name
        self.age=age

    def sleep(self):
        print('吃饭,睡觉,打豆豆')
    def say_no(self):
        print('name:%s,age:%s'%(self.name,self.age),end='')

class Student(Person):
    text='852'

# 由于父类已经存在一个方法可以完成这个三参数的初始化
# 所以可以直接调用父类的初始化完成这部分的初始化工作

def __init__(self,name ,age,number):
        # [1]指名道姓的调用
        Person.__init__(self,name,age)
        # [2]super()
        super().__init__(name,age)

        # py2的写法
        # super(Student, self).__init__(name,age,gender)

        self.number=number
        
        # 访问父类的属性
    def show_text(self):
        print(self.text)
        print(super().text)

    def say_hi(self):
        super().say_hi()
        print("my number: %s" % self.number)

s = Student("jack",20,"man",)
s.say_no()
View Code

调用 父类的初始化方法

当你继承一个现有的类,并且你覆盖了父类的init方法时,必须在初始化方法的第一行调用父类的初始化方法,并传入父类所需的参数 
View Code

例子:

class Person:
    def __init__(self,name,gender,age,*args):
        self.name = name
        self.gender = gender
        self.age = age
        self.aa()

    def aa(self):
        print("aa run")


    def say_hi(self):
        print("name:%s ,gender:%s,age:%s" % (self.name,self.gender,self.age))


class Student(Person):

    def __init__(self,name,gender,age,number):
        super().__init__(name,gender,age)
        self.number= number

    def say_hi(self):
        super().say_hi()
        print("numnber:%s" % self.number)

stu = Student("rose","mael",20,"old01")
stu.say_hi()
View Code

继承的原理,mro列表

即使没有直接继承关系,super仍然会按照mro继续往后查找

当你使用super()函数时,
# Python会在MRO列表上继续搜索下一个类。
# 只要每个重定义的方法统一使用super()并只调用它一次
# ,那么控制流最终会遍历完整个MRO列表,
# 每个方法也只会被调用一次
View Code

使用super调用的所有属性,都是从MRO列表当前的位置往后找

class A():
    # q=3
    pass

class B(A):
    # q=5
    pass

class C(A):
    q=9
    pass

class D(B,C):
    # q=15
    pass

Q=D()
print(Q.q)
print(D.mro()) 
View Code

组合

指的是 一个类把另一个类的对象作为自己的属性 就称之为组合
当你定义一个类 并且这个类拥有某种类型的属性时 就称之为组合
对象与对象的关系
都是用用来重用代码的方式:
组合描述的是 什么拥有什么的关系   学生 有 书  学生有手机
继承描述的是 什么是什么的关系      麦兜是猪    猪猪侠也是猪

例子

class Phone:
    def __init__(self,price,kind,color):
        self.price = price
        self.kind = kind
        self.color = color

    def call(self):
        print("正在呼叫XXXX;")

    def send_message(self):
        print("正在发送短信....")


class Student:
    def __init__(self,name,gender,phone):
        self.name = name
        self.gender = gender
        self.phone = phone

    def show_info(self):
        print("name:%s gender:%s" % (self.name,self.gender))

phone = Phone(1000,"apple","red")

stu1 = Student("rose","male",phone)
stu1.phone.call()
View Code

 

经典类与新式类

1.只有在python2中才分新式类和经典类,python3中统一都是新式类
2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类
3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类
3.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式

 

 

经典类:
  深度优先
新式类:
先深度 直到有一个公共父类时,查找其他路线(基于C3算法)

菱形继承

一个类有多个父类,多个父类又有一个公共的父类

 

 

class A:
    j = 1
    pass

class B:
    # j = 2
    pass

class C(A):
    # j = 3
    pass

class D(A):
    j = 4
    pass

class E(B,C,D):
    # j = 5
    pass

d = E()
print(d.j)
View Code

 

posted on 2019-07-25 21:32  我只想你  阅读(129)  评论(0编辑  收藏  举报