上次說__getitem__
時已經粗略、淺顯、簡單說過什麼是可迭代對象。下面是找到的一個比較好的科學解釋:
Python
中可迭代對象(Iterable)
並不是指某種具體的數據類型,它是指存儲了元素的一個容器對象,且容器中的元素可以通過__iter__( )
方法或__getitem__( )
方法訪問。
__iter__
方法的作用是讓對象可以用for … in obj
循環遍歷,__getitem__( )
方法是讓對象可以通過實例名[index]
的方式訪問實例中的元素。老猿認為這兩個方法的目的是Python實現一個通用的外部可以訪問可迭代對象內部數據的接口。
一個可迭代對象是不能獨立進行迭代的,Python中,迭代是通過for … in obj
來完成的。凡是可迭代對象都可以直接用for… in obj
循環訪問,這個語句其實做了兩件事:第一件事是調用__iter__()
獲得一個可迭代器,第二件事是循環調用__next__()
。
常見的可迭代對象包括:
a) 集合數據類型,如list、tuple、dict、set、str
等;
b) 生成器(generator
),包括生成器和帶yield
的生成器函數(generator function)
,下節專門介紹。
如何判斷一個對象是可迭代對象呢?具體判斷方法如下兩種:
利用numpy
的iterable
方法
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
中常見迭代的蹤影呢?
大概是因為深度學習的模型訓練往往需要很大的數據集,有時甚至以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