1、背景
在工作中,我們往往需要定義自己的數據結構,能夠使數據進行有效的讀取、序列結構就是重要的數據結構之一,利用python中的list、tuple、str、dict等都是一些內置的序列結構,我們可以用len()函數返回序列長度或者for循環進行遍歷元素,但實際上python的解釋器會在實現這些功能自動調用數據類中的特殊方法,例如len()調用的就是__len__(),for循環調用的是__iter__(),實際上python中的特殊方法是非常強大,能夠幫助我們有效的利用數據。
2、iterable、iterator、sequence
這裏來說一說iterable和iterator、以及sequence的區別。
iterable實際上是一個類對象,任何包含__iter__()或者__getitem__()的方法的對象,都可以被認爲是一個iterable。
sequence首先iterable的一種,顧名思義,sequence就是有有序的iterable,可以通過整數索引來訪問其中的元素。因此在sequence中需要定義__len__()和__getitem__()方法。
iterator對象的實現必須滿足迭代協議,python中這種迭代協議通過__next__()和__iter__()來實現。
(在hash類型數據中,__iter__()不能被__getitem__()代替。)
iterator用next()函數或者__next__()來訪問元素,且每次訪問iterator都會更新,能夠更有效率的利用內存(訪問完iterator就被清空了)。
這裏放一個前面深度學習定義的數據序列:
import os
from torch import nn
from PIL import Image
import numpy as np
class Mydataset(nn.module):
def __init__(self, images_dir:str,masks_dir:str, class_num:int, transform):
super(Mydataset,self).__init__():
self.class_num=class_num
self.names=os.listdir(images_dir)
self.images_fps=[os.path.join(images_dir,name) for name in self.names]
self.masks_fps = [os.path.join(masks_dir, name.split(".")[0]+".npy") for name in self.names]
self.transform=transform
def __len__(self):
return len(self.ids)
def __getitem__(self, i):
per_image=Image.open(self.images_fps[i])
per_mask=np.load(self.masks_fps[i])
per_mask[per_mask>self.class_num-1]=0
per_image=self.transform(per_image)
return per_image,per_mask
可以明顯的看出這是一個sequence。