码迷,mamicode.com
首页 > 其他好文 > 详细

d21天 继承

时间:2019-07-25 21:41:52      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:div   http   分类   and   class   expand   dac   短信   lse   

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

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

在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

 

d21天 继承

标签:div   http   分类   and   class   expand   dac   短信   lse   

原文地址:https://www.cnblogs.com/komorebi/p/11247138.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!