In Python definieert het 'Sequence' protocol een interface voor objecten die indexeerbaar en iteratief zijn, zoals lijsten of tuples. Historisch gezien zijn sequenties ontstaan vanaf de eerste versies van Python om natuurlijke bewerkingen op datastructuren te ondersteunen: indexering, slicing, en iteratie over elementen.
Probleem — om een gebruikersklasse zich als sequentie te laten gedragen, zijn alleen de methoden iter en next niet voldoende. Voor volledige ondersteuning van sequentiegedrag zijn extra methoden nodig.
Oplossing — om een eigen sequentietype te implementeren, moet je de methoden getitem (noodzakelijk voor indexering en slicing) en optioneel len (voor len() en om de lengte te controleren) definiëren. Zo zal het object iteratie, toegang via index, slicing en vele standaard Python-operaties met sequenties ondersteunen.
Voorbeeldcode:
class MyCounter: def __init__(self, stop): self._stop = stop def __getitem__(self, index): if 0 <= index < self._stop: return index * 10 else: raise IndexError('Out of range') def __len__(self): return self._stop c = MyCounter(5) print(c[3]) # 30 print(len(c)) # 5 for x in c: print(x)
Belangrijkste kenmerken:
Als ik alleen iter en next implementeer, wordt mijn object een Sequence?
Nee. Een dergelijk object zal alleen iterabel zijn (iterable), maar niet een sequentie. Het zal geen indexering, slicing, of standaard functies van lijstachtige objecten ondersteunen.
Is het verplicht om getitem te implementeren voor ondersteuning van de for-lus?
Niet verplicht. Als iter is geïmplementeerd, zal for werken. Maar als er geen iter is, zal de interpreter proberen getitem te gebruiken, te beginnen bij index 0, totdat er een IndexError optreedt. Daarom is voor een sequence voldoende dat getitem is geïmplementeerd.
Kan ik getitem alleen voor int implementeren en niet voor slice?
Technisch gezien zal het object werken voor c[0], maar een poging om een slice c[1:4] te nemen zal falen. Om slicing te ondersteunen, moet getitem in staat zijn om slice-objecten te verwerken (zie slice.indices en isinstance(key, slice)).
Voorbeeldcode:
class S: def __getitem__(self, idx): if isinstance(idx, slice): return [x for x in range(idx.start or 0, idx.stop or 10, idx.step or 1)] return idx * 2
Een aangepaste structuur geïmplementeerd, alleen iter gedefinieerd, denkend dat nu slicing en indexering mogelijk zijn.
Voordelen:
Nadelen:
Een klasse implementeert getitem met ondersteuning voor slicing en int-indexen, evenals len.
Voordelen:
Nadelen: