• 031.Python面向对象_类&补充_内置私有属性&特殊方法


    无奋斗不青春

    我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈
    入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈
    虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈
    PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈
    Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈
    优 质 资 源 下 载 :👉👉 资源下载合集 👈👈

    分隔线

    内置私有属性

    内置类私有属性

    • 内置类属性说明
      __dict__        # 类的属性和值
      __bases__       # 类的所有父类构成元组
      __doc__         # 类的文档字符串
      __name__        # 类名
      __module__      # 类定义所在的模块
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 示例
      class B(object):
          pass
      
      class Person(B,A):
          """Person类描述"""
          age = 18
      
          def test(self):
              """test方法描述"""
              print('test方法')
      
      
      print(Person.__dict__)          # 输出:{'__module__': '__main__', '__doc__': 'Person类描述', 'age': 18, 'test': }
      print(Person.__bases__)         # 输出:(, )
      print(Person.__doc__)           # 输出:Person类描述
      print(Person.__name__)          # 输出:Person
      print(Person.__module__)        # 输出:__main__(主模块)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

    内置实例私有属性

    • 内置实例属性说明
      __dict__        # 实例的属性
      __class__       # 实例对应的模块.类
      
      • 1
      • 2
    • 示例
      class A(object):
          pass
      
      class B(object):
          pass
      
      class Person(B,A):
          """Person类描述"""
          age = 18
      
          def __init__(self):
              a = 99
              self.b = 199
      
      
          def test(self):
              """test方法描述"""
              c = 100
              self.d = 200
              print('test方法')
      
      
      p = Person()
      p.name = '失心疯'
      print(p.__dict__)               # 输出:{'b': 199, 'name': '失心疯'}
      print(p.__class__)              # 输出:(主模块.Person类)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26

    内置特殊方法

    关于内置特殊方法

    • 作用
      • 当我们尝试去实现一些内置方法的时候,可以完成一些特定的功能
    • 常见特定功能
      • 初始化操作
      • 信息格式化操作
      • 调用操作
      • 索引操作
      • 切片操作
      • 迭代器
      • 描述器
      • 实现不同的内置方法,可以完成实例不同的特定操作

    内置特殊方法分类

    生命周期方法
    • 下一章节单独介绍
    其他内置方法
    初始化操作
    • 作用
      • 用于初始化实例变量。实例变量是对象的属性,用于存储数据
    • 实现方法
      • __init__方法
    • 示例代码
      class Person(object):
          def __init__(self, name, age):
              self.name = name
              self.age = age
              self.source = '地球'
      
      
      p1 = Person('张三', 18)
      p2 = Person('李四', 36)
      
      print(p1.name, p1.age, p1.source)       # 输出:张三 18 地球
      print(p2.name, p2.age, p2.source)       # 输出:李四 36 地球
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    信息格式化操作
    • 作用
      • 访问实例对象的时候,自动调用执行这个操作方法
    • 实现方法
      • __str__方法
      • __repr__方法
    • __str__方法示例
      class Person(object):
          def __init__(self):
              print('实例化对象的时候,自动调用__init__方法')
              self.name = '失心疯'
              self.age = 36
      
          def __str__(self):
              return f'调用__str__方法,我的名称是:{self.name}, 年龄是:{self.age}'
      
      
      p = Person()        # 输出:实例化对象的时候,自动调用__init__方法
      print(p)            # 输出:调用__str__方法,我的名称是:失心疯, 年龄是:36
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    • __repr__方法示例
      class Person(object):
          def __init__(self):
              print('实例化对象的时候,自动调用__init__方法')
              self.name = '失心疯'
              self.age = 36
      
          def __str__(self):
              return f'调用__str__方法,我的名称是:{self.name}, 年龄是:{self.age}'
      
          def __repr__(self):
              return f'调用__repr__方法,我的名称是:{self.name},年龄是:{self.age}'
      
      
      p = Person()                # 输出:实例化对象的时候,自动调用__init__方法
      print(p)                    # 输出:调用__str__方法,我的名称是:失心疯, 年龄是:36
      
      s = str(p)
      print(s, type(s))            # 调用__str__方法,我的名称是:失心疯, 年龄是:36 
      
      r = repr(p)
      print(r, type(r))           # 调用__repr__方法,我的名称是:失心疯,年龄是:36 
      
      p                           # 无输出
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
    • __str____repr__的区别
      • __str____repr__大致差不多,都是通过一个字符串来描述这个对象

      • 但是__str____repr__面向的角色不一样

        • __str__面向的角色是用户,看起来比较友好,易懂
        • __repr__面向的角色是开发人员(Python解释器),是为了让开发人员看到这个实例的本质(如:类型、内存地址),或者Python解释器通过eval这个函数再次把它处理成相关的实例对象
      • 在PyCharm中执行情况

        • 在这里插入图片描述
      • 在Python解释器中执行情况

        • 在这里插入图片描述
      • eval函数转换

        import datetime
        
        t = datetime.datetime.now()
        
        print(t)                # 执行__str__方法,输出:2023-11-04 21:07:49.773549
        print(repr(t))          # 行__repr__方法,输出:datetime.datetime(2023, 11, 4, 21, 7, 49, 773549)
        
        res = repr(t)
        print(res)              # 输出:datetime.datetime(2023, 11, 4, 21, 22, 53, 180571)
        print(eval(res))        # eval函数,输出:2023-11-04 21:09:06.275814
        
        # eval函数:将字符串str当成有效的表达式来求值并返回计算结果
        # eval(repr(t)) 相当于是下面的步骤
        aa = datetime.datetime(2023, 11, 4, 21, 7, 49, 773549)
        print(aa)
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
    调用操作
    • 作用

      • 使得“对象”具备当做函数来调用的能力
    • 实现方法

      • __call__方法

      • 默认实例化对象是不能被调用的

        class Person(object):
            pass
        
        
        p = Person()
        p()
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 在这里插入图片描述
      • 添加__call__方法后,实例化对象就可以实现调用功能

        class Person(object):
            def __call__(self, *args, **kwargs):
                print('__call__方法,实现调用功能')
        
        
        p = Person()
        p()
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 在这里插入图片描述
      • 同样,实例对象在调用的时候也是可以传入参数的

        class Person(object):
            def __call__(self, *args, **kwargs):
                print('__call__方法,实现调用功能')
                print('接收参数:', args, kwargs)
        
        
        p = Person()
        p(123, 456, 888, name='失心疯')
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 在这里插入图片描述
    • 应用场景

      • 场景要求:创建很多个画笔,画笔的类型(钢笔.铅第),画笔的颜色(红色、蓝色、黄色、绿色…)
      • 实现方法一:使用偏函数
        # 正常情况
        # def penFatory(pen_type, pen_color):
        #     print(f'生产一支{pen_type}类型的笔,颜色是:{pen_color}')
        #
        #
        # gb1 = penFatory('钢笔','红色')
        # gb2 = penFatory('钢笔','蓝色')
        # gb3 = penFatory('钢笔','黄色')
        # gb4 = penFatory('钢笔','绿色')
        
        # 在生成多种颜色的钢笔时,每次都要重复输入笔的类型:钢笔,这个比较累赘
        # 通过偏函数方式来优化
        
        # # 方式一:自定义偏函数
        # def penFatory(pen_type, pen_color):
        #     print(f'生产一支{pen_type}类型的笔,颜色是:{pen_color}')
        #
        # # 定义偏函数
        # def newPenFatory(new_color, new_type='钢笔'):
        #     penFatory(new_type, new_color)
        #
        #
        # gb1 = newPenFatory('红色')
        # gb2 = newPenFatory('蓝色')
        # gb3 = newPenFatory('黄色')
        # gb4 = newPenFatory('绿色')
        
        
        # 方式二:使用标准库functools
        import functools
        # 这里需要注意的是,需要将定义偏函数时传递的参数放到最后,否在则定义实例的时候会报错
        def penFatory(pen_color, pen_type):
            print(f'生产一支{pen_type}类型的笔,颜色是:{pen_color}')
        
        
        newPenFatory = functools.partial(penFatory, pen_type='钢笔')
        
        gb1 = newPenFatory('红色')
        gb2 = newPenFatory('黄色')
        gb3 = newPenFatory('蓝色')
        gb3 = newPenFatory('绿色')
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
      • 实现方法二:使用__call__方法
        # 使用__call__方法
        class PenFatory(object):
            def __init__(self, pen_type):
                self.type = pen_type
        
            def __call__(self, pen_color):
                print(f'生产一支{self.type}类型的笔,颜色是:{pen_color}')
        
        
        gb = PenFatory('钢笔')      # 实例化对象的时候,定义其类型为:钢笔
        
        gb('黄色')                  # 每次调用,设置其颜色
        gb('绿色')
        gb('蓝色')
        gb('红色')
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
    索引操作
    • 作用
      • 可以对一个实例对象进行索引操作(将我们所创建出来的实例对象,可以以一个字典或者列表的方式来进行操作)
    • 实现步骤
      • 1、实现三个内置方法
        • __setitem__方法
        • __getitem__方法
        • __delitem__方法
        • 语法示例
          class Person(object):
              def __setitem__(self, key, value):
                  print('setitem', key, value)
                  
              def __getitem__(self, item):
                  print('getitem', item)
                  
              def __delitem__(self, key):
                  print('delitem', key)
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
      • 2、可以以索引的形式操作对象
        • 增/改
          p[1] = 666
          p['s'] = '失心疯'
          
          • 1
          • 2
        • p[1]
          p['s']
          
          • 1
          • 2
        • del p['s']
          del p[1]
          
          • 1
          • 2
      • 示例代码
        class Person(object):
            def __init__(self):
                self.cache = {}
        
            def __setitem__(self, key, value):
                self.cache[key] = value
        
            def __getitem__(self, item):
                return self.cache[item]
        
            def __delitem__(self, key):
                del self.cache[key]
        
        
        p = Person()
        p['name'] = '失心疯'
        print(p['name'])
        del p['name']    
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
    切片操作
    • 作用
      • 可以对一个实例对象进行切片操作
    • 实现步骤
      • 已过期)Python2.x版本中通过__setspic____getspic____delspic__三个方法实现
      • Python3.x版本中统一由索引操作进行管理__setitem____getitem____delitem__
    • 代码示例
      class Person(object):
          def __init__(self):
              self.list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
      
          def __setitem__(self, key, value):
              print(key, value)
              self.list[key] = value
      
          def __getitem__(self, item):
              print(item)
              return self.list[item]
      
          def __delitem__(self, key):
              print(key)
              del self.list[key]
      
      
      p = Person()
      
      # 通过切片操作进行值的修改(切片操作不能直接添加值)
      p[0:4:2] = ['a', 'b']  # 执行__setitem__方法,输出:slice(0, 4, 2) ['a', 'b']
      # 从输出结果可以看到,key是一个slice实例对象(切片对象)
      # 查看 slice 切片实例对象 源码
      # start = property(lambda self: 0)      # 获取起始索引
      # """:type: int"""
      #
      # step = property(lambda self: 0)       # 获取步长
      # """:type: int"""
      #
      # stop = property(lambda self: 0)       # 获取结束索引
      # """:type: int"""
      
      # 通过切片获取值
      p[0:4:1]                # 执行__getitem__方法,输出:slice(0, 4, 1)
      
      # 通过切片删除值
      del p[0:2:1]            # 执行__delitem__方法,输出:slice(0, 2, 1)
      
      p[:]                    # 通过删除操作后,输出:['b', 4, 5, 6, 7, 8, 9]
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
    • 切片操作与索引操作都是通过__setitem____getitem____delitem__三个方法统一管理,所以我们在编写这三个方法的时候需要进行容错处理
      class Person(object):
          def __init__(self):
              self.cache = {}
              self.list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
      
          def __setitem__(self, key, value):
              # 判断key是否是slice类的子类
              if issubclass(key, slice): 
                  self.list[key] = value
              else:
                  self.cache[key] = value
      
          def __getitem__(self, item):
              if issubclass(item, slice):
                  return self.list[item]
              else:
                  return self.cache[item]
      
          def __delitem__(self, key):
              if issubclass(key, slice):
                  del self.list[key]
              else:
                  del self.cache[key]
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
    比较操作
    • 作用
      • 自定义两个对象“比较大小、是否相等”的规则
      • 比较运算符:=、!=、>、>=、<、<=
    • 实现步骤
      • 通过以下方法分别实现
      __eq__:是否等于(==)比较时,自动执行(没有写__ne__方法时,不等于比较时,会执行该方法)
      __ne__:是否不等于(!=)比较时,自动执行(不等于比较时,优先执行该方法)
      __gt__:是否大于(>)比较时,自动执行
      __ge__:是否大于等于(>=)比较时,自动执行
      __lt__:是否小于(<)比较时,自动执行
      __le__:是否小于等于(<=)比较时,自动执行
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 示例代码
      class Person(object):
          def __init__(self, age, width):
              self.age = age
              self.width = width
      
          # 通过下面方法设定两个对象进行比较时,比较的是age属性值
          def __eq__(self, other):
              """实例对象进行 == 比较时,自动调用"""
              return '__eq__方法', self.age == other.age
      
          def __ne__(self, other):
              """实例对象进行 != 比较时,自动调用"""
              return '__ne__方法', self.age != other.age
      
          def __gt__(self, other):
              """实例对象进行 > 比较时,自动调用"""
              return '__gt__方法', self.age > other.age
      
          def __ge__(self, other):
              """实例对象进行 >= 比较时,自动调用"""
              return '__ge__方法', self.age >= other.age
      
          def __lt__(self, other):
              """实例对象进行 < 比价时,自动调用"""
              return '__lt__方法', self.age < other.age
      
          def __le__(self, other):
              """实例对象进行 <= 比较时,自动调用"""
              return '__le__方法', self.age <= other.age
      
      
      p1 = Person(18, 160)
      p2 = Person(17, 180)
      
      print(p1 == p2)             # 输出:('__eq__方法', False)
      print(p1 != p2)             # 输出:('__ne__方法', True)
      print(p1 > p2)              # 输出:('__gt__方法', True)
      print(p1 >= p2)             # 输出:('__ge__方法', True)
      print(p1 < p2)              # 输出:('__lt__方法', False)
      print(p1 <= p2)             # 输出:('__le__方法', False)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
    • 注意事项
      • 1、如果对于方向操作的比较符(= 与 !=,> 与 <) ,只定义了其中一个昂发,但使用的是另一种比较运算时,解释器会采用调换参数的方式进行调用该方法
        class Person(object):
            def __init__(self, age, name):
                self.age = age
                self.name = name
        
            def __lt__(self, other):
                """实例对象进行 < 比价时,自动调用"""
                print('self:', self.name, self.age)
                print('other:', other.name, other.age)
                return  self.age < other.age
        
        p1 = Person(18, 'p1')
        p2 = Person(19, 'p2')
        
        print(p1 < p2)
        # self: p1 18
        # other: p2 19
        # True
        
        print(p1 > p2)    # 实际执行的是 p2 < p1 比较
        # self: p2 19
        # other: p1 18
        # False    
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
      • 2、几个方法不支持叠加操作(有==和<比较,并不能实现 <= 比较)
        class Person(object):
            def __init__(self, age):
                self.age = age
        
            def __eq__(self, other):
                """实例对象进行 == 比较时,自动调用"""
                return self.age == other.age
        
            def __lt__(self, other):
                """实例对象进行 < 比价时,自动调用"""
                return self.age < other.age
        
        
        p1 = Person(18)
        p2 = Person(19)
        
        print(p1 == p2)     # 输出:False
        print(p1 < p2)      # 输出:True
        
        print(p1 <= p2)     # 报错:TypeError: '<=' not supported between instances of 'Person' and 'Person'        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
      • 3、通过一个装饰器(functools.total_ordering)实现方法叠加操作(实现==和<方法,即可实现 != 、> 、>=、<=的比较)
        import functools
        
        
        @functools.total_ordering
        class Person(object):
            def __init__(self, age, name):
                self.age = age
                self.name = name
        
            def __eq__(self, other):
                """实例对象进行 == 比较时,自动调用"""
                print('__eq__方法')
                return self.age == other.age
        
            def __lt__(self, other):
                """实例对象进行 < 比价时,自动调用"""
                print('__lt__方法', self.name, other.name)
                return self.age < other.age
        
        
        # print(Person.__dict__)
        """
        输出:{'__module__': '__main__', '__init__': , 
                '__eq__': , '__lt__': , 
                '__dict__': , '__weakref__': , 
                '__doc__': None, '__hash__': None, 
                '__gt__': , 
                '__le__': , 
                '__ge__': }
        """
        p1 = Person(29, 'p1')
        p2 = Person(29, 'p2')
        
        print(p1 == p2)             # 输出:__eq__方法   True
        print(p1 != p2)             # 输出:__eq__方法   False
        #
        print(p1 < p2)              # 输出:__lt__方法   False
        print(p1 <= p2)             # 输出:__lt__方法   __eq__方法    True
        # 首先执行 < 判断,返回True, 则结束,
        #               返回False,再执行 == 判断
        #
        print(p1 > p2)              # 输出:__lt__方法   __eq__方法    False
        # 首先执行 < 判断,返回True,  则结束,返回:<判断结果取反False
        #               返回False, 再执行 == 判断,返回:==判断结果取反
        
        print(p1 >= p2)             # 输出:__lt__方法   True
        # 首先执行 < 判断,最终返回:<判断结果取反
        # < 判断结果为True,则不会是大于和等于,所以返回False
        # < 判断结果为False, 则不是大于就是等于,所以返回True
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
    上下文布尔值
    • 作用
      • 控制实例对象返回的布尔值(True/False)
    • 实现步骤
      • __bool__方法控制
      • 非0即真,非空即真
    • 示例代码
      # 对比示例
      class Person(object):
          pass
      
      
      p = Person()
      
      # 非空即真,p是实例对象,并非为空,所以判断为真,执行下面代码
      if p:
          print('xxxxx')
      else:
          print('yyyyy')
      # 输出:xxxxx
      
      
      # __bool__方法演示示例
      class Person(object):
          def __bool__(self):
              return False
      
      
      p = Person()
      
      if p:
          print('xxxxxx')
      else:
          print('yyyyyy')
      
      # 输出:yyyyyy
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
    • 通过__bool__方法,我们就可以控制实例对象判断的返结果
    • 如:如果实例对象的年龄大于18则返回True,否则返回False
      class Person(object):
          def __init__(self, age, name):
              self.age = age
              self.name = name
      
          def __bool__(self):
              return self.age > 18
      
      
      p1 = Person(16, 'p1')
      p2 = Person(26, 'p2')
      
      ps = [p1, p2]
      
      for p in ps:
          if p:
              print(f'{p.name}已经成年啦')
          else:
              print(f'{p.name}还是未成年')
      
      # 输出结果
      # p1还是未成年
      # p2已经成年啦
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
    遍历操作
    • 作用

      • 实现通过遍历操作访问实例对象(能进行for...in..遍历 和 next()函数访问操作)
    • 实现步骤

      • __getitem__方法
      • __iter__ + __next__ 方法(优先级更高)
    • 示例代码

    • 对比示例

      class Person(object):
          pass
      
      
      p = Person()
      for i in p:
          print('xxxx')
          
      # 输出结果:报错
      # TypeError: 'Person' object is not iterable
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • __getitem__方法示例

      class Person(object):
          def __init__(self):
              self.age = 18
      
          def __getitem__(self, item):
              self.age += 1
              if self.age > 30:
                  raise StopIteration('年龄太大了...')
              return self.age
      
      
      p = Person()
      
      # for..in..操作会不断调用__getitem__方法,直到该方法抛出异常(raise StopIteration)
      for i in p:
          print(i)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    • 这里的for..in..遍历是直接调用__getitem__方法

    • __iter__ + __next__ 方法示例

      class Person(object):
          def __init__(self):
              self.age = 18
      
          def __iter__(self):
              print('xxxx')
              """实例对象调用iter()方法的时候自动调用,需要返回一个迭代器(iterator)对象"""
              return self
      
          def __next__(self):
              """实例对象使用next()函数的时候自动调用该方法"""
              self.age += 1
              if self.age > 30:
                  raise StopIteration('年龄太大了!')
              return self.age
      
      
      p = Person()
      
      # 通过for..in..遍历
      # 1、先通过iter()方法将实例对象转换成一个迭代器
      # iter(p)           # 输出:xxxx
      # 2、再调用next()方法取值
      for i in p:
          print(i)
      
      # 通过next()函数取值
      print(next(p))
      print(next(p))
      print(next(p))
      print(next(p))
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
    • 这里的for..in..实际是先通过iter()方法将实例对象转换成迭代器对象,再调用next()方法

      • 执行iter()方法的时候会自动调用__iter__()方法
      • 执行next()方法的时候会自动调用__next__()方法
    补充:迭代相关内容
    • 可使用next()方法:对象内部实现__next__()方法

      class Person(object):
          def __init__(self):
              self.age = 18
      
          def __next__(self):
              self.age += 1
              if self.age > 20:
                  raise StopIteration
              return self.age
      
      
      p = Person()
      print(next(p))          # 19
      print(next(p))          # 20
      
      import collections
      
      # 判断实例对象是否是可迭代对象
      print(isinstance(p, collections.Iterable))      # False
      
      # 判断实例对象是否是迭代器
      print(isinstance(p, collections.Iterator))      # False
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
    • 可迭代对象:对象内部实现__iter__()方法

      class Person(object):
          def __init__(self):
              self.age = 18
      
          def __iter__(self):
              return self
      
      
      p = Person()
      # print(next(p))          # 报错:TypeError: 'Person' object is not an iterator
      # print(next(p))          # 报错:TypeError: 'Person' object is not an iterator
      
      from collections import abc
      
      # 判断实例对象是否是可迭代对象
      print(isinstance(p, abc.Iterable))      # True
      
      # 判断实例对象是否是迭代器
      print(isinstance(p, abc.Iterator))      # False
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    • 迭代器:对象内部既要实现__next__()方法又要实现__iter__()方法

      class Person(object):
          def __init__(self):
              self.age = 18
      
          def __iter__(self):
              return self
      
          def __next__(self):
              self.age += 1
              if self.age > 20:
                  raise StopIteration
              return self.age
      
      
      p = Person()
      
      from collections import abc
      
      # 判断实例对象是否是可迭代对象
      print(isinstance(p, abc.Iterable))      # True
      
      # 判断实例对象是否是迭代器
      print(isinstance(p, abc.Iterator))      # False
      
      print(next(p))          # 19
      print(next(p))          # 20
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
    • iter()函数的使用

      • 作用:将一个实例对象转换成一个迭代器
    • 语法

      iter(实例对象)
      iter(可执行对象,)
      
      • 1
      • 2
    • iter(实例对象)模式将实例对象转换成迭代器

      • 想要通过for..in..遍历自定义实例对象,可以通过以下两种方式

        • 1、在自定义实例对象中实现__getitem__()方法
        • 2、在自定义实例对象中实现__iter__()方法和__next__()方法
      • 要想使用iter()方法将自定义实例转换成一个迭代器,必须通过以下两种方法中的任意一种

        • 1、在自定义实例对象中实现__getitem__()方法
        • 2、在自定义实例对象中实现__iter__()方法和__next__()方法
      • 示例1:实例对象内部实现__getitem__()方法

        class Person(object):
            def __init__(self):
                self.age = 18
        
            def __getitem__(self, item):
                self.age += 1
                if self.age > 25:
                    raise StopIteration
                return self.age
        
        
        p = Person()
        pt = iter(p)
        print(pt)               # 
        
        for i in pt:
            print(i)
        
        # 输出结果
        # 19
        # 20
        # 21
        # 22
        # 23
        # 24
        # 25
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
      • 示例2:在实例对象内部只实现__iter__()方法

        class Person(object):
            def __init__(self):
                self.age = 18
        
            def __iter__(self):
                return self
        
        
        p = Person()
        pt = iter(p)            # 报错:TypeError: iter() returned non-iterator of type 'Person'
        
        # 报错原因:
            # 使用iter()函数时会自动调用__iter__()方法,__iter__()方法要求返回值是一个迭代器,此处返回的是self(示例对象本身)
            # 但是此时的Person类内部仅仅只实现了__iter__()方法,并没有实现__next__()方法,所以Person类实例化出来的对象仅仅是一个可迭代对象并不是一个迭代器
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
      • 示例3:在示例对象内部实现__iter__()方法和__next__()方法

        class Person(object):
            def __init__(self):
                self.age = 18
        
            def __iter__(self):
                return self
        
            def __next__(self):
                self.age += 1
                if self.age > 25:
                    raise StopIteration
                return self.age
        
        
        p = Person()
        pt = iter(p)
        print(pt)                   # 输出:<__main__.Person object at 0x000001B574C4DFD0>
        # 执行iter()函数,实际就是执行的自定义类对象中的__iter__()方法,返回的是self(Person实例化对象本身p)
        # 因为Person类内部实现了`__iter__()`方法和`__next__()`方法,所以实例化出来的对象p就是一个迭代器
        # 因此:pt就是p,就是一个迭代器,就可以通过for..in..遍历,也可以通过next()函数访问值
        print(pt == p, pt is p)     # 输出:True True
        # for i in pt:
        #     print(i)
        
        print(next(p))
        print(next(p))
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26

    • 特殊方法汇总
    __init__(self)
        # 创建实例化对象的时候会自动调用
    
    __setattr__(self, key, value)
        # 实例新增/修改属性的时候自动调用
    
    __str__(self)
        # 访问实例对象的时候自动调用
    
    __repr__(self)
        # 访问实例对象的时候自动调用
    
    __setitem__(self, key, value)
        # 实例对象以key-value的方式添加属性和值的时候自动调用
        # 实例对象通过切片进行值修改的时候自动调用,key是slice类型
    
    __getitem__(self, item)
        # 实例对象以key-value的方式获取属性值的时候自动调用
        # 实例对象通过切片进行值获取的时候自动调用,item是slice类型
        # 实例对象进行for..in..遍历时候不断调用该方法,直到方法抛异常,优先级低于__iter__方法
    
    __delitem__(self, key)
        # 实例对象以key-value的方式删除属性和值的时候自动调用
        # 实例对象通过切片进行值删除的时候自动调用,key是slice类型
        
    __eq__(self, other):
        # 实例对象进行 == 比较时,自动调用
    
    __ne__(self, other):
        # 实例对象进行 != 比较时,自动调用
    
    __gt__(self, other):
        # 实例对象进行 > 比较时,自动调用
    
    __ge__(self, other):
        # 实例对象进行 >= 比较时,自动调用
    
    __lt__(self, other):
        # 实例对象进行 < 比价时,自动调用
    
    __le__(self, other):
        # 实例对象进行 <= 比较时,自动调用
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
  • 相关阅读:
    天猫京东整站商品数据分析,天猫商品价格数据接口,京东商品价格数据接口,电商平台商品价格数据接口流程介绍
    springboot+avue医院绩效考核系统源码
    IronPDF for .NET 2023.9.8 Crack
    使用js开发一个快速打开前端项目的alfred插件
    R语言使用t.test函数执行t检验验证总体均值是否是某个特定的值(从样本集推论总体均值)
    脑肽载体Angiopep-2、906480-05-5、TFFYGGSRGKRNNFKTEEY
    卷积神经网络入门
    Linux的防火墙: netfilter防火墙框架, iptables , CentOS的firewalld, Ubuntu的ufw
    [实验报告]--基于端口安全
    Angular 中的数据交互GET POST
  • 原文地址:https://blog.csdn.net/weixin_50296259/article/details/134325233