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__方法被调用!
    结果

     

  • 相关阅读:
    由铭心提供的免费邮箱
    BT面板安装教程
    Onedrive分享型网盘搭建
    cookie与session
    IntelliJ Idea 2017 免费激活方法
    什么情况下出现的redis
    tomcat编码问题
    idea启动项目报Unable to open debugger port (127.0.0.1:11480): java.net.SocketException "socket closed"
    Sentry异常捕获平台
    亚瑟·阿伦博士的36个问题
  • 原文地址:https://www.cnblogs.com/LXP-Never/p/9373484.html
Copyright © 2011-2022 走看看