• python封装enclosure


    封装enclosure

      封装是指隐藏类的实现细节,让使用者不关心这些细节
      封装的目的是让使用者能过尽可能少的方法或属性操作对象
      python的封装是模拟的封装

    私有属性和方法:
      python类中以双下划线'__' 开头,不以双下划线结尾的标识符为私有成员,私有成员只能使用方法进行访问和修改

      两种:
      私有属性
      私有方法--- 只能让该类的方法来调用

      class A:
        def __init__(self):
          self.__money = 0
    
        def show_money(self):
          print("self.__money = ",self.__money)
        def make_money(self, m):
          self.__money += m
      a = A()
      a.__money = 100 # 修改属性
      print(a.__money) # 属性取值
      a.show_money() # 0
      a.make_money(999)
      a.show_money() # 999
    View Code

    多态 polymorphic:
      字面意思是"多种状态"
      多态是指在有继承/派生关系的类中,调用基类的对象的方法,实际能调用子类的覆盖方法的现象叫多态
      状态:
        静态(编译时状态)
        动态(运行时状态)
      说明:
        python全部对象都只有运行时状态,没有编译时状态

      class A:
        def do(self):
          print("A")
    
      class B(A):
        def do(self):
          print("B")
    
      class C(B):
        def do(self):
          print('C')
    
      def work(obj):
        obj.do() # 请问调用谁?
    
      L = [A(), B(), C(), B()]
      for x in L:
        work(x)
    View Code

    多继承 multiple inheritance
      多继承是指一个子类继承自两个或两个以上的基类

      语法:
        class 类名(基类名1, 基类名2, ....):
          语句块
      说明:
        一个子类同时继承自多个父类,父类中的方法可以同时被继承下来
        如果两个父类中有同名的方法,而在子类中又没有覆盖此方法时,调用结果难以确定

      class Plane:
        def fly(self, height):
          print("飞机以海拔", height, "米的高度飞行")
    
      class Car:
        def run(self, speed):
          print("汽车以", speed, 'km/h的速度行驶')
    
      class PlaneCar(Plane, Car):
        '''PlaneCar同时继承自汽车类和飞机类'''
    
      pc = PlaneCar()
      pc.run(300)
      pc.fly(10000)
    View Code

    多继承的问题(缺陷)
      标识符冲突的问题
      要谨慎使用多继承

      # 小张写了一个类A:
      class A:
        def m(self):
          print("A")
    
      # 小李写了一个类B
      class B:
        def m(self):
          print("B")
    
      # 小王感觉小张和小李写的类自己可以用
      class AB(A, B):
        pass
    
      ab = AB()
      ab.m() # 调用谁由继承列表中先后顺序来决定
    View Code

    多继承的问题MRO(method resolution order)问题
      类的 __mro__属性
        用来记录每个类的方法的查找顺序

    用MRO来确定钻石继承的方法查找顺序
        A
        /
       B C
        /
        D

      class A:
        def go(self):
          print("A")
    
      class B(A):
        def go(self):
          print("B")
          super().go() # C
    
      class C(A):
        def go(self):
          print("C")
          super().go() # A
    
      class D(B, C):
        def go(self):
          print('D')
          super().go()
    
      d = D()
      d.go() # ???
    View Code

    面向对象编程语言特征
      封装
      继承
      多态

    面向对象的编程语言:
      C++, C#, Python, Java, objective-c, swift, ...

    函数(方法)重写
      在自定义的类内添加相应的方法,让自定义的类创建的实例像内建对象一样进行内建函数操作

    对象转字符串函数的重写(覆盖)
      repr(obj) 返回一个符合Python语法规则的字符串:
        通常:
          eval(repr(obj)) == obj
      str(obj) 通过给定的对象返回一个字符串(这个字符串通常是给人阅读的)

    说明:
      1. str(obj) 函数先查找obj.__str__() 方法,调用此方法并返回结果
      2. 如果obj.__str__() 方法不存在,则调用obj.__repr__()方法并返回结果
      3. 如果obj.__repr__方法不存在,则调用object类的__repr__实例方法显示<__main__.XXX object at 0xAABBCCDD>格式的字符串

      # 此示例示意 重写__repr__ 和 __str__方法,实现自定义类的
      # 个性化显示
    
      class MyNumber:
        def __init__(self, value=0):
          self.data = value
    
        def __str__(self):
          '''此方法必须返回字符串'''
          print("__str__方法被调用")
          return "数字:%d" % self.data
    
        def __repr__(self):
          return "MyNumber(%d)" % self.data
    
      n1 = MyNumber(100)
      print("repr(n1)=", repr(n1))
      # print("str(n1)=", n1.__str__()) # ???
      print("str(n1) =", str(n1)) # 数字: 100
      print(n1) # 内部会调用str(n1)
    
      n2 = MyNumber(200)
      print("repr(n2)=", repr(n2)) # repr(n2)-->n2.__repr__()
    View Code

    重载方法:
      repr() 函数对应 def __repr__(self):
      str() ---------> def __str__(self):

    内建函数的重写
      __abs__      abs(obj)
      __len__      len(obj)
      __reversed__   reversed(obj)
      __round__     round(obj)

      class MyList:
        def __init__(self, iterable=()):
          self.data = [x for x in iterable]
    
        def __len__(self):
          '''此函数必须只有一个形参self,此函数必须返回整数'''
          # return self.data.__len__()
          return len(self.data)
    
        def __repr__(self):
          return 'MyList(%s)' % self.data
    
        def __abs__(self):
          L = [abs(x) for x in self.data]
          return MyList(L) # 创建一个新的MyList对象并返回
    
      myl = MyList([1, -2, 3, -4, 5])
      print(len(myl)) # myl.__len__()
      myl2 = abs(myl) # myl.__abs__()
      print(myl2) # MyList([1, 2, 3, 4, 5])
    View Code

    数据转换函数重写
      __complex__    complex(obj)
      __int__      int(obj)
      __float__     float(obj)
      __bool__     bool(obj)

      class MyNumber:
        def __init__(self, value=0):
          self.data = value
    
        def __repr__(self):
          return "MyNumber(%d)" % self.data
    
        def __int__(self):
          '''此方法必须返回整数'''
          return int(self.data)
    
      n1 = MyNumber(100)
      x = int(n1) # x = 100 # x = n1.__int__()
      print(x)
    View Code

    布尔测试函数重写
      作用:
        用于bool(obj) 函数取值
        用于if语句真值表达式取值
        用于while 语句真值表达式取值
      方法名: __bool__
      说明:
        当存在__bool__方法时,调用obj.__bool__() 取值
        当不存在__bool__方法时,调用obj.__len__() 取值
        当再不存在__len__方法时,直接返回True

      class MyList:
        def __init__(self, iterable=()):
          self.data = [x for x in iterable]
    
        def __len__(self):
          '''返回0为假值,返回非零值为真值'''
          return len(self.data)
    
        def __bool__(self):
          return all(self.data)
    
      myl = MyList([1, -2, 3, -4, 5])
      print(myl)
      print(bool(myl)) # ???
      if myl:
        print("")
      else:
        print("")
    View Code

    迭代器(高级)
      迭代器可以能过next(obj) 函数取值的对象,就是迭代器

      迭代器协议:
        迭代器协议是指对象能够使用next函数获取下一项数据,在没有下一项数据时触发一个StopIteration异常来终止迭代的约定

      迭代器协议的实现方法:
        __next__(self)

    可迭代对象:
      是指能用iter(obj) 函数返回迭代器的对象
      可迭代对象的实现方法:
        __iter__(self)

      class MyList:
        def __init__(self, iterable=()):
          self.data = [x for x in iterable]
    
        def __repr__(self):
          return 'MyList(%s)' % self.data
    
        def __iter__(self):
          return MyListIterator(self.data)
    
      class MyListIterator:
        def __init__(self, data):
          self.data = data
          self.cur_index = 0 # 用来记录当前访问位置的索引
    
        def __next__(self):
          '''此方法需要实现迭代器协议'''
          if self.cur_index >= len(self.data):
            raise StopIteration # 通知调用者停止迭代
          r = self.data[self.cur_index]
          self.cur_index += 1
          return r
    
      # import time
      myl = MyList([1, -2, 3, -4, 5])
      print(sum(myl)) # 3
      print(max(myl)) # 5
    
      # it = iter(myl) # it = myl.__iter__()
      # while True:
      #  try:
      #    x = next(it) # x = it.__next__()
      #    print(x)
      #    time.sleep(1)
      #  except StopIteration:
      #    break
    
      for x in myl:
        print(x) # 1 -2 3 -4 5
    View Code
  • 相关阅读:
    google的几道面试题
    轮盘赌算法
    基于packstack的openstack单节点安装
    攻克python3-字典(第四篇)
    攻克python3-列表与元组(第三篇)
    攻克python3-字符串(第二篇)
    攻克python3(第一篇)
    二维数组
    小白对c语言指针的基础总结
    小白对c语言数组的基础总结
  • 原文地址:https://www.cnblogs.com/zhaoyang1997/p/10707027.html
Copyright © 2020-2023  润新知