Python 类抽象与继承 派生覆盖 组合 属性查找顺序 新式类菱形继承

一 继承与抽象(类与类之间的关系)

1.什么是继承:在程序中继承是描述类与类之间的关系。例如:A类继承了B类,A类就能直接使用B类已经存在的方法和属性(A类称之为子类,B类称之为父类也叫基类)

2.为什么要使用继承:继承的一方可以直接使用被继承一方已经存在的方法和属性。其目的是为了提高代码的复用性。

3.继承语法

class 父类名称:
    类的内容 

class 子类名称(父类名称):
    类的内容 
    
#在python中 一个子类可以同时继承多个父类 
View Code

抽象

1.什么是抽象:将多个子类中相同的属性和方法,进行抽取形成一个新的类。再有别的子类们进行继承。

2.例:

class Teacher:
    school = "oldboy"
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def say_hi(self):
        print("hello i am %s" % self.name)
        
    def teach(self):
        print("正在教书......")

class Student(Teacher):
    pass
# 问题:学生类继承了老师类,所以学生类都具备了老师类的name,age属性和say_hi,teacher方法。但是teacher方法应该是老师独有的,学生不应该具备。
# 解决:抽象

class OldBoyPerson:
    school = "oldboy"
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def say_hi(self):
        print("hello i am %s" % self.name)

class Teacher(OldBoyPerson):
    def teach(self):
        print("正在教书......")


class Student(OldBoyPerson):
    pass
# 学生类和老师类继承了OldBoyPerson类,都具备name,age属性和say_hi,teacher方法。但是teacher方法应该是老师独有的,学生不具备。
View Code

3.继承的正确使用:先抽象再继承

二 对象属性和方法正确的查找顺序

class A:
    text = "haha"

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

b = B()
b.text = "xixi"

print(b.text) # xixi"

对象自己的 - > 所在类中 -> 找父类 - >父类的父类 ->Object
View Code

三 继承中的覆盖与派生

1.什么是覆盖(重写):指的是子类中出现了与父类相同的属性或方法。(根据查找顺序就会优先查找自己的即覆盖了父类的属性和方法。

2什么是派生:子类中出现了和父类不一样的属性或方法。

class Person:
    name = 'person'
    def say_hi(self):
        print("hello")

class Student(Person):
    name = 'student'  # 覆盖
    age= 18 # 派生
    def say_hi(self): # 覆盖
        print("hello world!")




stu = Student()
print(stu.name) # student
print(stu.age) # 18
stu.say_hi() # hello world!
View Code

四 继承中子类中访问父类的内容的三种方式

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

class Parent:
    text = "abc"

    def say_something(self):
        print("anything")

class Sub(Parent):

    def show_info(self):
        # print(super(Sub,self).text)
        # super(Sub,self).say_something()

        # 访问方式2  py3的新语法 最常用的方式
        print(super().text)
        super().say_something()

        #方式3 直接指定类名调用
        # print(Parent.text)
        # Parent.say_something(self)


sub = Sub()
sub.show_info() # abc anything
View Code
class Person:
    text = "321"
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

    def sleep(self):
        print("人类 午睡 躺着睡!")

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

    
class Student(Person):
    text = "123"
    def __init__(self,name,age,gender,number):
        #======================================================================重点在这里
        # 由于父类已经存在一个方法可以完成这个三参数的初始化
        # 所以可以直接调用父类的初始化完成这部分的初始化工作
        # 方法1
        # Person.__init__(self,name,age,gender) # 指名道姓的调用

        # 方法2  在py2中不支持
        super().__init__(name,age,gender)

        # 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)
        # print("my name :%s my age :%s my gender: %s my number: %s" % (self.name, self.age, self.gender,self.number))


s = Student("jack",20,"man","007")
s.say_hi()
# s.show_text()

五 组合

1.什么是组合:将一个对象作为另一个对象的属性称之为组合(指的是对象与对象之间的关系

2.组合描述的是 什么拥有什么的关系   学生 有 书  学生有手机

class PC:
    def open_app(self,app_name):
        print("open %s" % app_name)

class OldBoyStudent:
    def __init__(self,PC,notebook):
        self.PC = PC
        self.notebook = notebook
    pass

pc = PC()
notebook = PC()


stu = OldBoyStudent(pc,notebook)
View Code
stu.notebook.open_app("pycharm")
组合的目的:

也是为了重用现有代码

什么时候使用继承:分析两个类的关系,到底是不是:什么是什么的关系

什么时候使用组合:如果两个类之间 没有太大的关系,完全不属于同类

另外组合相比继承,耦合度更低了

六 新式类和经典类

1.新式类:python3中任何类都直接或间接继承了object,python3中全都是新式类

2.经典类:既不是object的子类,仅在python2中出现,,

当出现了菱形继承时,新式类,先深度,当遇到了共同父类时就广度

class A:
    # a = 1
    pass

class B(A):
    # a = 2
    pass

class C(A):
    # a = 3
    pass

class D(A):
    # a = 4
    pass

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

e1 = E()
# print(e1.a)
# 新式类的顺序
# E  B C D A object 
# 经典类的顺序
# E B A C D
# print(E.mro())

注意:经典类没有mro列表

七 实现一个可以限制元素的类型的列表

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

"""
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
class A:
    # a = 1
    pass

class B(A):
    # a = 2
    pass

class C(A):
    # a = 3
    pass

class D(A):
    # a = 4
    pass

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

e1 = E()
# print(e1.a)
# 新式类的顺序
# E  B C D A object
# 经典类的顺序
# E B A C D
print(E.mro()) # <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]

# 注意:经典类没有mro列表
View Code
posted @ 2019-07-25 21:17  心慌得初夏  阅读(330)  评论(0编辑  收藏  举报
levels of contents