• Python for循环与__getitem__的关系记录


    一个类里面如果有__iter__,for循环就是找它取,没有的话就会找__getitem__。

    如果自己定义类的话,我自己觉的还是先定义好__iter__比较好,因为如果调用__getitem__来执行循环读取速度也应该不会快,而且逻辑理解更加复杂。

    前面一笔看过没有留心具体的执行情况。

    In [169]: class Foo: 
         ...:     def __getitem__(self, pos): 
         ...:         print(pos) 
         ...:         return range(10)[pos] 
         ...:     
    
    In [172]: for i in f: 
         ...:     ... 
         ...:      
         ...:                                                                                          
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    

    当一个for循环或者list,tuple去读取该对象的数据时,

    将会启动一个whileTrue的死循环,会从0开始迭代读取+1读取数据并根据return 返回。

    如果没有设置StopIteration或者IndexError错误来停止循环,这是一个无法停下来的循环。

    从代码可以看出,如果没有报错或者设置显式的条件,这个for循环会无线循环。

    我现在设置一个显式的设置。

    In [173]: class Foo: 
         ...:     def __getitem__(self, pos): 
         ...:         if pos >5: 
         ...:             raise StopIteration 
         ...:         print(pos) 
         ...:         return range(10)[pos] 
         ...:          
    
    In [177]: for i in f: 
         ...:     ... 
         ...:                                                                                          
    0
    1
    2
    3
    4
    5
    

    将错误设置为IndexError也可以执行,但TypeError就不行了。

         ...:     def __getitem__(self, pos): 
         ...:         if pos >5: 
         ...:             raise IndexError 
         ...:         print(pos) 
         ...:         return range(10)[pos] 
         ...:                                                                                          
    
    In [182]:                                                                                          
    
    In [182]: f = Foo()                                                                                
    
    In [183]: for i in f: 
         ...:     ... 
         ...:                                                                                          
    0
    1
    2
    3
    4
    5
    

    如果用list去运行这个参数会把返回的一个一个元素,装入列表当中:

    In [184]: list(f)                                                                                  
    0
    1
    2
    3
    4
    5
    Out[184]: [0, 1, 2, 3, 4, 5]
    

    只有__getitem__的类的实例是属于可迭代对象,但用isinstances测试collections.Iterable是不能通过的,书后面介绍可以通过iter函数来测试,如果没报错就说明是可迭代对象,然后生成一个没有__next__属性的迭代器。

    In [185]: from collections import Iterable                                                         
    
    In [186]: isinstance(f, Iterable)                                                                  
    Out[186]: False
    
    In [187]: iter(f)                                                                                  
    Out[187]: <iterator at 0x114f2be50>
    
     dir(f)                                                                                   
    Out[189]: 
    ['__class__',
     '__delattr__',
     '__dict__',
     '__dir__',
     '__doc__',
     '__eq__',
     '__format__',
     '__ge__',
     '__getattribute__',
     '__getitem__',
     '__gt__',
     '__hash__',
     '__init__',
     '__init_subclass__',
     '__le__',
     '__lt__',
     '__module__',
     '__ne__',
     '__new__',
     '__reduce__',
     '__reduce_ex__',
     '__repr__',
     '__setattr__',
     '__sizeof__',
     '__str__',
     '__subclasshook__',
     '__weakref__']
    


  • 相关阅读:
    MyBatis学习(五)resultMap测试
    MyBatis学习(四)XML配置文件之SQL映射的XML文件
    Mybatis学习(三)XML配置文件之mybatis-config.xml
    每次回顾,总会有一点小收获!
    php数组去重、魔术方法、redis常用数据结构及应用场景
    MySQL使用可重复读作为默认隔离级别的原因
    后端程序猿标配之linux命令
    常用字符串函数
    nginx配置隐藏index.php
    MySQL的sql_mode解析与设置
  • 原文地址:https://www.cnblogs.com/sidianok/p/12128004.html
Copyright © 2020-2023  润新知