Python之封装、继承和多态

封装、继承和多态

面向对象有三大特性:封装、继承和多态

封装

  • 封装是指将数据与具体操作的实现代码放在某个对象内部,使这些代码的实现细节不被外界发现且不能通过任何形式修改对象内部实现,正是由于封装机制。
    • 打码平台示例代码:http://www.ttshitu.com/
  • 作用:
    • 程序在使用某一对象时不需要关心该对象的数据结构细节及实现操作的方法。
    • 使用封装能隐藏对象实现细节,使代码更易维护,同时因为不能直接调用、修改对象内部的私有信息,在一定程度上保证了系统安全性。

继承

  • 继承来源于现实世界:
    • 一个最简单的例子就是孩子会具有父母的一些特征,即每个孩子都会继承父亲或者母亲的某些特征,当然这只是最基本的继承关系,现实世界中还存在着更复杂的继承。
  • 在OOP程序设计中,当我们定义一个新类的时候,新的类称为子类(Subclass),而被继承的类称为基类、父类或超类(Base class、Super class)。
    • 继承最大的好处是子类获得了父类的全部变量和方法的同时,又可以根据需要进行修改、拓展。其语法结构如下:
    • class Father():
          pass
      class Son(Father):
          pass
      
  • Python支持多父类的继承机制。
继承示例代码:
# 查看子类(学生)是否可以继承到父类(人)的属性和方法
class Person():
    classVar = 'value'
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def speak(self):
        print('person can speak')
    @classmethod
    def classFunc(cls):
        print('I am Person classFunc')
    @staticmethod
    def staticFunc():
        print('I am Person staticFunc')

class Student(Person):
    pass

s1 = Student('zhangsan',20,'F')             # 子类可以继承父类的构造方法
print(s1.name,s1.age,s1.sex)                # 子类可以继承父类的实例变量
print(Student.classVar)                     # 子类可以继承父类的类变量
s1.speak()                                  # 子类可以继承父类的实例方法
Student.classFunc()                         # 子类可以继承父类的类方法和静态方法
Student.staticFunc()

派生

  • 子类添加自己独有的方法或属性
class Person():
    classVar = 'value'
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def speak(self):
        print('person can speak')
    @classmethod
    def classFunc(cls):
        print('i am Person classFunc')
    @staticmethod
    def staticFunc():
        print('i am Person staticFunc')

class Student(Person):
    address = 'beijing'                     # 子类自己派生出来的类变量
    # 如何让子类派生出自己独有的实例变量
    def __init__(self,classNum,score,name,age,sex):
        super().__init__(name,age,sex)      # 调用父类的构造方法,作用从父类中继承过来实例变量
        # classNum和score就是子类自己派生出来的实例变量
        self.classNum = classNum
        self.score = score
    # 子类自己派生出来的方法
    def learning(self):
        pass


s1 = Student(3,100,'zhangsan',20,'sex')     # 子类可以继承父类的构造方法

Student.classFunc()                         # 子类可以继承父类的类方法和静态方法
  • super函数
    • 如果你想强制调用父类的成员该如何实现呢?使用super()函数!这是一个非常重要的函数,最常见的就是通过super调用父类的实例化方法__init__
      • 语法:super(子类名, self).方法名(),需要传入的是子类名和self,调用的是父类里的方法,按父类的方法需要传入参数。
super通常是作用在子类的构造方法中,在子类的构造方法中通过super调用父类的构造方法,从而可以让子类继承到父类的实例变量

重写

思考:如果子类从父类中继承过来的方法,满足不了子类的应用,怎么办呢?
class Father():
    def __init__(self,h):
        self.h = h
    def hobby(self):
        return self.h
    
class Son(Father):
    def __init__(self,h,a1,a2):
        self.a1 = a1
        self.a2 = a2
        super().__init__(h)
    def hobby(self):
        #在继承父类原始方法操作的基础上新增添一些操作经即可
        h_list = super().hobby()
        h_list.append(self.a1)
        h_list.append(self.a2)
        return h_list

单继承

  • 继承的作用:
  • 实现了程序的高复用,大大缩短程序的开发周期!
  • 算法补充
    • #:a+b+c=1000,a**2 + b**2 = c**2
      for a in range(1001):
          for b in range(1001):
              c = 1000 - a - b
              if a+b+c == 1000 and a**2 + b**2 == c**2:
                  print(a,b,c)
      
    • 衡量算法性能好坏的方式:时间复杂度
      • 时间复杂度:量化算法执行步骤的数量.
        • 大O记法来表示时间复杂度:
          • 将时间复杂度执行步骤数量对应表达式(2n+n**2)中最有意义的一项提取出来放置在O后面的括号里即可.
          • O(n**2)
    • 排序算法:冒泡排序
      • 1.乱序系列中的两两元素进行大小比较,将比较出较大的元素逐步向后偏移(序列中最大的值就已经偏移到最后了)
        # def sort(alist):
        #     for i in range(len(alist)-1):#控制元素两两比较的次数
        #         if alist[i] > alist[i+1]:
        #             alist[i],alist[i+1] = alist[i+1],alist[i]
        #     return alist
        
        #2.将第一步的操作继续一次作用在前n个乱序的序列中
        def sort(alist):
            for j in range(len(alist)-1):
                for i in range(len(alist)-1-j):#控制元素两两比较的次数
                    if alist[i] > alist[i+1]:
                        alist[i],alist[i+1] = alist[i+1],alist[i]
            return alist
        alist = [3,8,5,7,6,2,1]
        print(sort(alist))
        
在多继承的时候要注意:
  • 子类在调用某个方法或变量的时候,首先在自己内部查找,如果没有找到,则开始根据继承机制在父类里查找。
  • 根据类的父类定义中的顺序,以深度优先的方式逐一查找父类!

示例1:设想有下面的继承关系:

#B和E类中各自有一个相同的show方法,则A继承B和E后,直接调用show,则最终执行的show到底是B的还是E的?
class D():
    pass
class C(D):
    pass
class B(C):
    def show(self):
        print('B()->show')

class G():
    pass
class F(G):
    pass
class E(F):
    def show(self):
        print("E()->show")

class A(B,E):
    pass

A().show()
so,在A的定义中,继承参数的书写有先后顺序,写在前面的被优先继承。
那如果B没有show方法,而是D有呢?
class D():
    def show(self):
        print('D()->show')
class C(D):
    pass
class B(C):
    pass

class G():
    pass
class F(G):
    pass
class E(F):
    def show(self):
        print("E()->show")

class A(B,E):
    pass

A().show()
左边具有深度优先权,当一条路走到黑也没找到的时候,才换另一条路。

示例2:

那如果继承结构是这样的呢?类D和类G又同时继承了类H。当只有B和E有show方法的时候,无疑和上面的例子一样,找到B就不找了,直接打印"i am B"。但如果是只有H和E有show方法呢?
class H():
    def show(self):
        print('H()->show')
class D(H):
    pass
class C(D):
    pass
class B(C):
    pass

class G(H):
    pass
class F(G):
    pass
class E(F):
    def show(self):
        print("E()->show")

class A(B,E):
    pass

A().show()

我们想当然地以为会打印"i am H",因为深度优先嘛。但是,打印的却是"i am E"!为什么?因为在这种情况下,Python的搜索路径是这样的:

遇到更复杂的继承情况呢?

上述两种继承图还是不太难的,也不能代表所有!实际上其它的继承模式,仔细一解剖,都能划分成上面两种情况

type和isinstance

  • isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
  • isinstance() 方法的语法:
    • isinstance(object, classinfo)
      参数:
          object -- 实例对象。
          classinfo -- 可以是类名、基本类型或者有它们组成的元组。
      返回值:
      		如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。
      
    • #isinstance和type的基本使用
      
  • type:返回对象的类型
  • isinstance() 与 type() 区别:
    • type() 不会认为子类是一种父类类型,不考虑继承关系。
    • isinstance() 会认为子类是一种父类类型,考虑继承关系。
    • class A():
          pass
      class B(A):
          pass
      a = 10
      b = B()
      print(type(a),isinstance(a,int))
      #认为在面向对象,一个子类对象可以被视为父类类型
      print(type(b),isinstance(b,A))
      

ce() 与 type() 区别:

  • type() 不会认为子类是一种父类类型,不考虑继承关系。
  • isinstance() 会认为子类是一种父类类型,考虑继承关系。
  • class A():
        pass
    class B(A):
        pass
    a = 10
    b = B()
    print(type(a),isinstance(a,int))
    #认为在面向对象,一个子类对象可以被视为父类类型
    print(type(b),isinstance(b,A))
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值