程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python魔法方法之__iter__

編輯:Python

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)
    

    運行結果:

    顯示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


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved