zoukankan      html  css  js  c++  java
  • python 多态、多继承、函数重写、迭代器

    用于类的函数 issubclass(cls,class_or_tuple)

    判断一个类是否继承自其他的类,如果此类cls是class或tuole中的一个派生(子类)则返回True,否则返回False

    封装 enclosure

    封装的目的是让使用者尽可能少的引用实例变量(属性)进行操作

    私有属性:python类中,以双下划线‘__’开头,不以双下划线结尾的标识符为私有成员,在类的外部无法直接访问。

     1 class A:
     2     def __init__(self):
     3         self.__p1 = 100  #__p1为私有属性,在类的外部不可访问
     4 
     5     def test(self):
     6         print(self.__p1)  # 可以访问
     7         self.__m1()  # A类的方法可以调用A类的私有方法
     8 
     9     def __m1(self):
    10         '''我是私有方法,只有我自己的类中的方法才能调用我哦'''
    11         print("我是A类的__m1方法!")
    12 
    13 a = A()  # 创建对象
    14 # print(a.__p1)  # 在类外看不到__p1属性,访问失败!
    15 a.test()
    16 # a.__m1()  # 出错.无法调用私有方法
    __私有属性

    多态 polymorphic

    多态是指在继承派生关系的类中,调用基类对象的方法,实际能调用子类的覆盖版本方法的现象叫多态

     1 class Shape:
     2     def draw(self):
     3         print("Shape.draw被调用")
     4 
     5 class Point(Shape)
     6     def draw(self):
     7         print('正在画一个点')
     8 
     9 class Circle(Point):
    10     def draw(self):
    11         print("正在画一个圆")
    12 
    13 def my_draw(s):
    14     s.draw()  # 此处显示出多态中的动态
    15 
    16 s1 = Circle()
    17 s2 = Point()
    18 my_draw(s1)  # 调用Circle里的draw 正在画一个圆
    19 my_draw(s2)  # 调用Point里的draw 正在画一个点
    多态

    多继承 multiple inheritance

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

    说明:一个子类可以同时继承自多个父类,父类中的方法可以同时被继承下来。如果两个父类中有同名的方法,而在子类中又没有覆盖此方法时,调用结果难以确定

     1 class Car:
     2     def run(self, speed):
     3         print("汽车以", speed, '公里/小时的速度行驶')
     4 
     5 class Plane:
     6     def fly(self, height):
     7         print("飞机以海拔", height, '的高度飞行')
     8 
     9 class PlaneCar(Car, Plane):
    10     '''PlaneCar同时继承自汽车类和飞机类'''
    11 
    12 p1 = PlaneCar()
    13 p1.fly(10000)
    14 p1.run(300)
    多继承

    多继承的问题(缺陷):名字冲突问题,要谨慎使用多继承(会先使用第一个继承的基类

     1 class A:
     2     def m(self):
     3         print("A.m()被调用")
     4 
     5 class B:
     6     def m(self):
     7         print('B.m()被调用')
     8 
     9 class AB(A, B):
    10     pass
    11 
    12 ab = AB()
    13 ab.m()  # A.m()被调用
    命名冲突

    继承的MRO(Method Resolution Order)问题

      的__mro__属性用来记录继承方法的查找顺序

     1 class A:
     2     def m(self):
     3         print("A.m")
     4 class B(A):
     5     def m(self):
     6         print("B.m")
     7 class C(A):
     8     def m(self):
     9         print("C.m")
    10 class D(B, C):
    11     '''d类继承自B,C'''
    12     def m(self):
    13         print("D.m")
    14 d = D()
    15 print(D.__mro__)
    16 #(<class '__main__.D'>, 
    17 # <class '__main__.B'>, 
    18 # <class '__main__.C'>, 
    19 # <class '__main__.A'>, 
    20 # <class 'object'>)
    21 d.m()  # 调用方法的顺序如上所示
    多继承顺序
     1 class A:
     2     def m(self):
     3         print("A.m")
     4 class B(A):
     5     def m(self):
     6         print("B.m")
     7         super().m()
     8 class C(A):
     9     def m(self):
    10         print("C.m")
    11         super().m()
    12 class D(B, C):
    13     '''d类继承自B,C'''
    14     def m(self):
    15         print("D.m")
    16         super().m()
    17 d = D()
    18 d.m()  # 调用方法的顺序是什么?
    19 
    20 for x in D.__mro__:
    21     print(x)
    22 
    23 
    24 # D.m
    25 # B.m
    26 # C.m
    27 # A.m
    28 # <class '__main__.D'>
    29 # <class '__main__.B'>
    30 # <class '__main__.C'>
    31 # <class '__main__.A'>
    32 # <class 'object'>
    多继承顺序

    函数重写

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

    对象转字符串函数:

      repr(obj) 返回一个能代表此对象的表达式字符串,通常eval(repr(obj))==obj (这个字符串通常是给python解释执行器运行用的)

    对象转字符串函数的重写方法

      reper(obj)函数的重写方法:  def__repr__(self):

                        return 能够表达self内容的字符串

      str(obj)函数的重写方法:  def__str__(self):

                        return 人能看懂的字符串

     1 class MyNumber:
     2     def __init__(self, value):
     3         self.data = value
     4     def __str__(self):
     5         print("__str__被调用")
     6         return "数字: %d" % self.data
     7     def __repr__(self):
     8         print("__repr__被调用")
     9         return 'MyNumber(%d)' % self.data
    10 n1 = MyNumber(100)
    11 # print(str(n1))  # 调用 n1.__str__(self);__str__被调用;数字: 100
    12 # print(repr(n1)) #__repr__被调用  MyNumber(100)
    13 print(n1)   # ;__str__被调用;数字: 100
    14 # n2 = eval("MyNumber(100)")
    15 # print(n2)   #__str__被调用;数字: 100
    重写方法

    说明:

    1、str(obj)函数先调用obj.__str__()方法,调用此方法并返回字符串

    2、如果obj没有__str__()方法,则调用obj.__repr__()方法返回的字符串

    3、如果obj没有__repr__()方法,则调用object类的__repe__()实例方法显示<xxxx>格式的字符串

    数值转换函数的重写

      def __complex__(self)  complex(obj) 函数调用
      def __int__(self)    int(obj) 函数调用
      def __float__(self)   float(obj) 函数调用
      def __bool__(self)    bool(obj) 函数调用

     1 '''此示例示意自定义的类MyNumber能够转成为数值类型'''
     2 class MyNumber:
     3     def __init__(self, v):
     4         self.data = v
     5     def __repr__(self):
     6         return "MyNumber(%d)" % self.data
     7     def __int__(self):
     8         '''此方法用于int(obj) 函数重载,必须返回整数
     9         此方法通常用于制订自义定对象如何转为整数的规则
    10         '''
    11         return 10000
    12 
    13 n1 = MyNumber(100)
    14 print(type(n1))
    15 # if n1 == 100:
    16 #     print("n1 == 100")
    17 n  = int(n1)
    18 print(type(n))
    19 print(n)
    自定义类可以转成数值类型
    1 <class '__main__.MyNumber'>
    2 <class 'int'>
    3 10000
    结果

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

     1 # 自定义一个MyList类,与系统内建的类一样,
     2 # 用来保存有先后顺序关系的数据
     3 
     4 class MyList:
     5     '''自定义列表类'''
     6     def __init__(self, iterator=[]):
     7         self.data = [x for x in iterator]
     8 
     9     def __repr__(self):
    10         return "MyList(%r)" % self.data
    11 
    12     def __abs__(self):
    13         # return MyList([abs(x) for x in self.data])
    14         # 上一句语句可以用如下生成表达式代替已防止过多占内存
    15         return MyList((abs(x) for x in self.data))
    16 
    17     def __len__(self):
    18         # return self.data.__len__()
    19         return len(self.data)
    20 
    21 myl = MyList([1, -2, 3, -4])
    22 print(myl)
    23 print(abs(myl))  # MyList([1, +2, 3, +4])
    24 print("原来的列表是:", myl)
    25 
    26 myl2 = MyList(range(10))
    27 print(myl2)
    28 print('myl2的长度是:', len(myl2))
    29 print('myl的长度是: ', len(myl))
    View Code
    1 MyList([1, -2, 3, -4])
    2 MyList([1, 2, 3, 4])
    3 原来的列表是: MyList([1, -2, 3, -4])
    4 MyList([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    5 myl2的长度是: 10
    6 myl的长度是:  4
    结果

     布尔测试函数的重写

      格式 def __bool__(self):
        ...
    作用:
      用于bool(obj) 函数取值
      用于if语句真值表达式中
      用于while语句真值表达式中
    说明:
      1. 优先调用__bool__方法取值
      2. 如果不存在__bool__方激动 ,则用__len__()方法取值后判断是否为零值,如果不为零返回True,否则返回False
      3. 如果再没有__len__方法,则直接返回True

     1 class MyList:
     2     '''自定义列表类'''
     3     def __init__(self, iterator=[]):
     4         self.data = [x for x in iterator]
     5 
     6     def __repr__(self):
     7         return "MyList(%r)" % self.data
     8 
     9     def __bool__(self):
    10         print("__bool__方法被调用!")
    11         return False
    12 
    13     # def __len__(self):
    14     #     print("__len__被调用")
    15     #     return len(self.data)
    16 
    17 myl = MyList([1, -2, 3, -4])
    18 print(bool(myl))  # False
    19 if myl:
    20     print("myl 是真值")
    21 else:
    22     print("myl 是假值")
    View Code
    1 __bool__方法被调用!
    2 False
    3 __bool__方法被调用!
    4 myl 是假值
    结果

     迭代器(高级)

    可以通过next(it) 函数取值的对象就是迭代器
    迭代器协议:迭代器协议是指对象能够使用next函数获取下一项数据,在没有下一项数据时触发一个StopIterator来终止迭代的约定
    实现方法:类内需要有 __next__(self) 方法来实现迭代器协议
    语法形式:
      class MyIterator
        def __next__(self):
          迭代器协议的实现
          return 数据

    可迭代对象是指能用iter(obj) 函数返回迭代器的对象(实例),可迭代对象内部一定要定义__iter__(self)方法来返回迭代器

    可迭代对象的语法形式:
      class MyIterable:
        def __iter__(self):
          语句块
          return 迭代器

     1 # 此示例示意可迭代对象和迭代器的定义及使用方式:
     2 class MyList:
     3     def __init__(self, iterator):
     4         '''自定义列表类的初始化方法,此方法创建一个data实例
     5         变量来绑定一个用来存储数据的列表'''
     6         self.data = list(iterator)
     7 
     8     def __repr__(self):
     9         '''此方法了为打印此列表的数据'''
    10         return 'MyList(%r)' % self.data
    11 
    12     def __iter__(self):
    13         '''有此方法就是可迭代对象,但要求必须返回迭代器'''
    14         print("__iter__方法被调用!")
    15         return MyListIterator(self.data)
    16 
    17 class MyListIterator:
    18     '''此类用来创建一个迭代器对象,用此迭代器对象可以迭代访问
    19     MyList类型的数据'''
    20     def __init__(self, iter_data):
    21         self.cur = 0  # 设置迭代器的初始值为0代表列表下标
    22         # it_data 绑定要迭代的列表
    23         self.it_data = iter_data
    24 
    25     def __next__(self):
    26         '''有此方法的对象才叫迭代器, 
    27         此方法一定要实现迭代器协议'''
    28         print("__next__方法被调用!")
    29         # 如果self.cur已经超出了列表的索引范围就报迭代结束
    30         if self.cur >= len(self.it_data):
    31             raise StopIteration
    32         # 否则尚未迭代完成,需要返回数据
    33         r = self.it_data[self.cur]  # 拿到要送回去的数
    34         self.cur += 1  # 将当前值向后移动一个单位
    35         return r
    36 
    37 myl = MyList([2, 3, 5, 7])
    38 print(myl)
    39 
    40 for x in myl:
    41     print(x)  # 此处可以这样做吗?
    42 
    43 # it = iter(myl)
    44 # x = next(it)
    45 # print(x)
    46 # x = next(it)
    47 # print(x)
    48 # x = next(it)
    49 # print(x)
    View Code
     1 MyList([2, 3, 5, 7])
     2 __iter__方法被调用!
     3 __next__方法被调用!
     4 2
     5 __next__方法被调用!
     6 3
     7 __next__方法被调用!
     8 5
     9 __next__方法被调用!
    10 7
    11 __next__方法被调用!
    结果

     

  • 相关阅读:
    JavaScript
    94.Binary Tree Inorder Traversal
    144.Binary Tree Preorder Traversal
    106.Construct Binary Tree from Inorder and Postorder Traversal
    105.Construct Binary Tree from Preorder and Inorder Traversal
    90.Subsets II
    78.Subsets
    83.Merge Sorted Array
    80.Remove Duplicates from Sorted Array II
    79.Word Search
  • 原文地址:https://www.cnblogs.com/LXP-Never/p/9373484.html
Copyright © 2011-2022 走看看