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

无奋斗不青春

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

分隔线

内置私有属性

内置类私有属性

  • 内置类属性说明
    __dict__        # 类的属性和值
    __bases__       # 类的所有父类构成元组
    __doc__         # 类的文档字符串
    __name__        # 类名
    __module__      # 类定义所在的模块
    
  • 示例
    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': <function Person.test at 0x000001F2C19D4280>}
    print(Person.__bases__)         # 输出:(<class '__main__.A'>, <class '__main__.B'>)
    print(Person.__doc__)           # 输出:Person类描述
    print(Person.__name__)          # 输出:Person
    print(Person.__module__)        # 输出:__main__(主模块)
    

内置实例私有属性

  • 内置实例属性说明
    __dict__        # 实例的属性
    __class__       # 实例对应的模块.类
    
  • 示例
    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__)              # 输出:<class '__main__.Person'>(主模块.Person类)
    

内置特殊方法

关于内置特殊方法

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

内置特殊方法分类

生命周期方法
  • 下一章节单独介绍
其他内置方法
初始化操作
  • 作用
    • 用于初始化实例变量。实例变量是对象的属性,用于存储数据
  • 实现方法
    • __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 地球
    
信息格式化操作
  • 作用
    • 访问实例对象的时候,自动调用执行这个操作方法
  • 实现方法
    • __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
    
  • __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 <class 'str'>
    
    r = repr(p)
    print(r, type(r))           # 调用__repr__方法,我的名称是:失心疯,年龄是:36 <class 'str'>
    
    p                           # 无输出
    
  • __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)
      
调用操作
  • 作用

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

    • __call__方法

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

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

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

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

    • 场景要求:创建很多个画笔,画笔的类型(钢笔.铅第),画笔的颜色(红色、蓝色、黄色、绿色…)
    • 实现方法一:使用偏函数
      # 正常情况
      # 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('绿色')
      
    • 实现方法二:使用__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、实现三个内置方法
      • __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)
        
    • 2、可以以索引的形式操作对象
      • 增/改
        p[1] = 666
        p['s'] = '失心疯'
        
      • p[1]
        p['s']
        
      • del p['s']
        del p[1]
        
    • 示例代码
      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']    
      
切片操作
  • 作用
    • 可以对一个实例对象进行切片操作
  • 实现步骤
    • 已过期)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]
    
  • 切片操作与索引操作都是通过__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]
    
    
比较操作
  • 作用
    • 自定义两个对象“比较大小、是否相等”的规则
    • 比较运算符:=、!=、>、>=、<、<=
  • 实现步骤
    • 通过以下方法分别实现
    __eq__:是否等于(==)比较时,自动执行(没有写__ne__方法时,不等于比较时,会执行该方法)
    __ne__:是否不等于(!=)比较时,自动执行(不等于比较时,优先执行该方法)
    __gt__:是否大于(>)比较时,自动执行
    __ge__:是否大于等于(>=)比较时,自动执行
    __lt__:是否小于(<)比较时,自动执行
    __le__:是否小于等于(<=)比较时,自动执行
    
  • 示例代码
    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、如果对于方向操作的比较符(= 与 !=,> 与 <) ,只定义了其中一个昂发,但使用的是另一种比较运算时,解释器会采用调换参数的方式进行调用该方法
      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    
      
    • 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'        
      
    • 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__': <function Person.__init__ at 0x00000138AF224280>, 
              '__eq__': <function Person.__eq__ at 0x00000138AF244A60>, '__lt__': <function Person.__lt__ at 0x00000138AF2451F0>, 
              '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, 
              '__doc__': None, '__hash__': None, 
              '__gt__': <function _gt_from_lt at 0x00000138AF074DC0>, 
              '__le__': <function _le_from_lt at 0x00000138AF074E50>, 
              '__ge__': <function _ge_from_lt at 0x00000138AF074EE0>}
      """
      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
      
上下文布尔值
  • 作用
    • 控制实例对象返回的布尔值(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
    
  • 通过__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已经成年啦
    
遍历操作
  • 作用

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

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

  • 对比示例

    class Person(object):
        pass
    
    
    p = Person()
    for i in p:
        print('xxxx')
        
    # 输出结果:报错
    # TypeError: 'Person' object is not iterable
    
    
  • __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)
    
  • 这里的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))
    
  • 这里的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
    
  • 可迭代对象:对象内部实现__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
    
  • 迭代器:对象内部既要实现__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
    
  • iter()函数的使用

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

    iter(实例对象)
    iter(可执行对象,)
    
  • 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)               # <iterator object at 0x000002626777DF10>
      
      for i in pt:
          print(i)
      
      # 输出结果
      # 19
      # 20
      # 21
      # 22
      # 23
      # 24
      # 25
      
    • 示例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类实例化出来的对象仅仅是一个可迭代对象并不是一个迭代器
      
    • 示例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))
      

  • 特殊方法汇总
__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):
    # 实例对象进行 <= 比较时,自动调用
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失心疯_2023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值