Python魔法方法之__iter__

Python魔法方法之__iter__

一个形象的科学解释

上次说__getitem__时已经粗略、浅显、简单说过什么是可迭代对象。下面是找到的一个比较好的科学解释:

Python中可迭代对象(Iterable)并不是指某种具体的数据类型,它是指存储了元素的一个容器对象,且容器中的元素可以通过__iter__( )方法或__getitem__( )方法访问。

  1. __iter__方法的作用是让对象可以用for … in obj循环遍历,__getitem__( )方法是让对象可以通过实例名[index]的方式访问实例中的元素。老猿认为这两个方法的目的是Python实现一个通用的外部可以访问可迭代对象内部数据的接口。

  2. 一个可迭代对象是不能独立进行迭代的,Python中,迭代是通过for … in obj来完成的。凡是可迭代对象都可以直接用for… in obj循环访问,这个语句其实做了两件事:第一件事是调用__iter__()获得一个可迭代器,第二件事是循环调用__next__()

  3. 常见的可迭代对象包括:
    a) 集合数据类型,如list、tuple、dict、set、str等;
    b) 生成器(generator),包括生成器和带yield的生成器函数(generator function),下节专门介绍。

  4. 如何判断一个对象是可迭代对象呢?具体判断方法如下两种:

    • 利用numpyiterable方法

      from numpy import iterable
      print(iterable(实例名))
      
    • 利用collections模块的Iterable

      from collections import Iterable
      isinstance(实例名, Iterable)
      

    以上内容均来自于CSDN的老猿Python,确实是大师之作,讲得简略、清晰关键是还能让人看懂,大佬!

一个典型的实例

  • 随便定义一个对象,不定义__iter__方法:

    from numpy import iterable
    
    class MyList:
        def __init__(self, len: int):
            self.list = [i for i in range(len)]
            self.length = len
    
        def __repr__(self) -> str:
            return f"MyList({self.length}):{self.list}"
    
    
    x = MyList(10)
    for i in x:
        print(i)
    
    

    运行结果:

    image-20220628161745515

    显示MyList实例是不可迭代的

    • 定义__iter__方法后

      • 下面的例子简单实现一个range(n)
      from numpy import iterable
      
      class MyList:
          def __init__(self, len: int):
              self.cursor = -1
              self.length = len
      
          def __iter__(self):
              return self
      
          def __next__(self):
              if self.cursor+1 < self.length:
                  self.cursor += 1
                  return self.cursor
              else:
                  exit(1)
      
          def __repr__(self) -> str:
              return f"MyList({self.length})"
      
      
      x = MyList(10)
      print(iterable(x))
      for i in x:
          print(i)
      
      

      输出为:

      True
      0
      1
      2
      3
      4
      5
      6
      7
      8
      9
      

      使用next()一步一步迭代可以看的更清楚:

      from numpy import iterable
      
      
      class MyList:
          def __init__(self, len: int):
              self.cursor = -1
              self.length = len
      
          def __iter__(self):
              return self
      
          def __next__(self):
              if self.cursor+1 < self.length:
                  self.cursor += 1
                  return self.cursor
              else:
                  exit(1)
      
          def __repr__(self) -> str:
              return f"MyList({self.length})"
      
      
      x = MyList(10)
      print(iter(x))
      print(next(x))
      print(next(x))
      print(next(x))
      print(next(x))
      for i in x:
          print(i)
      

      输出结果为:

      MyList(10)
      0
      1
      2
      3
      4
      5
      6
      7
      8
      9
      

可迭代对象的典型使用之PyTorch的数据加载器:Dataloader

为什么在PyTorch中常见迭代的踪影呢?

  • 大概是因为深度学习的模型训练往往需要很大的数据集,有时甚至以TB(1024GB)来计算,众所周知,大多数个人电脑的内存不超过32GB,一次性把1TB那么大的数据加载到内存当中使用,显然是不现实的

  • 这种情况下,把需要的数据集依次分批加载到内存中进行使用明显是更优更现实的方案,这与可迭代对象的概念与定位是不谋而合的,可以断言,正是因为Python天然支持迭代,所以Python在深度学习领域的地位非其他语言可以动摇。

Dataloader加载数据的实例:

from cgi import test
from torch.utils.data import DataLoader
from torchvision.transforms import ToTensor
from torchvision.datasets import CIFAR10
from numpy import iterable
# 使用CIFAR10参考数据集
test_set = CIFAR10(root='./torch2Learn/dataset/cifar10_data',
                   train=False, download=True, transform=ToTensor())

# 将数据集分批载入,每批64个
test_loader = DataLoader(dataset=test_set, batch_size=64,
                         shuffle=True, drop_last=False)
print(type(test_set))
print(type(test_loader))
print(iterable(test_set))
print(iterable(test_loader))
print(iter(test_loader))

for step, item in enumerate(test_loader):
    imgs_arr, kinds_arr = item

Python魔法方法之__iter___第1张图片

你可能感兴趣的:(Python,深度学习,python,numpy,pytorch,深度学习)