Een speciale class is de sequentie. Ik heb al een aantal sequentie classes geïntroduceerd, namelijk tuples, lists, dictionaries, en sets. Zulke classes bevatten een serie elementen, die je kunt benaderen middels een index of een key. Je kunt zelf ook een sequentie class creëren, door een aantal methodes die informatie over elementen van de class geven te overloaden.

Om te demonstreren hoe deze methodes werken, heb ik een sequentie geïmplementeerd die een Filippine puzzel beschrijft. Deze puzzel bestaat uit een serie vragen, die ieder beantwoordt kunnen worden met één woord. Van ieder antwoord is één letter “speciaal.” Als je de speciale letters achter elkaar zet, krijg je de oplossing van de puzzel.

Ik heb ieder van de puzzelwoorden gedefinieerd als een instantie van de class FilippineWoord, die als attributen heeft het antwoord, de index van de speciale letter in het antwoord, en de vraag. De class Filippine is de complete puzzel, dat wil zeggen, een sequentie van FilippineWoorden. Ik heb de methodes __len__(), __getitem__(), __setitem__(), en __delitem__() geïmplementeerd (de laatste twee worden in de code hieronder niet gebruikt).

class FilippineWoord:
    def __init__( self, woord, index, vraag ):
        self.woord = woord
        self.index = index
        self.vraag = vraag

class Filippine:
    def __init__( self, naam, woorden ):
        self.naam, self.woorden = naam, woorden
    def __len__( self ):
        return len( self.woorden )
    def __getitem__( self, n ):
        return self.woorden[n]
    def __setitem__( self, n, waarde ):
        self.woorden[n] = waarde
    def __delitem__( self, n ):
        del self.woorden[n]
    def toon( self ):
        print( self.naam )
        for i in range( len( self ) ):
            print( "{}. {}".format( i+1, self[i].vraag ),
                end = "  " )
            for j in range( len( self[i].woord ) ):
                if j == self[i].index:
                    print( "* ", end="" )
                else:
                    print( "_ ", end="" )
            print()
    def oplossing( self ):
        s = ""
        for i in range( len( self ) ):
            s += self[i].woord[self[i].index]
        return s

puzzel = Filippine(
    "De Monty Python en de Heilige Graal Filippine",
    [ FilippineWoord( "ANTHRAX", 5,
          "Sir Galahad bestormde kasteel" ),
      FilippineWoord( "BORS", 2, "Een konijn doodde Sir" ),
      FilippineWoord( "TIM", 0, "De wijze tovenaar heet" ),
      FilippineWoord( "HERBERT", 0,
          "De erfgenaam van het Moeras Kasteel is prins" ),
      FilippineWoord( "ZWALUW", 4,
          "Een kokosnoot is te zwaar voor een Europese" ),
      FilippineWoord( "MINSTREELS", 5,
          "De ridders aten Robins" ) ] )

puzzel.toon()

Ik heb nog twee methodes geïmplementeerd, die demonstreren hoe de hierboven genoemde methodes werken. toon() toont de puzzel, en gebruikt als zodanig de len() functie en indices om de woorden te benaderen. oplossing() toont de oplossing van de puzzel, en gebruikt ook len() en indices.

Het zou overigens mooier geweest zijn als ik de sterretjes, die de speciale letters aangeven, onder elkaar had afgedrukt. Het is echter afhankelijk van de editor die je gebruikt of er een vaste letterbreedte is, en dus is het lastig om dat voor elkaar te krijgen. Je kunt hier zelf een oplossing voor implementeren als je wilt (voor dit hoofdstuk is dat niet van belang).

Er is nog een belangrijke methode die je voor een sequentie class kunt implementeren, namelijk __iter__(). Ik stel een discussie van deze methode echter uit tot hoofdstuk 24.

Als je een sequentie class bouwt, kun je overwegen om ook de methode __add__() te implementeren, en wellicht ook een goede interpretatie van de methode __mul__().

Een Zin is een list van woorden. Een basale Zin class is hieronder gegeven. Implementeer de __len__(), __getitem__(), __setitem__(), en __contains__() methodes voor deze class.

class Zin:
    def __init__( self, words ):
        self.words = words
    def __repr__( self ):
        return " ".join( self.words )

s = Zin( [ "Er", "is", "slechts", "een", "ding", "ter",
"wereld", "erger" "dan", "beroddeld", "worden", "en",
"dat", "is", "niet", "beroddeld", "worden" ] )
print( s )
print( len( s ) )
print( s[7] )
s[7] = "prettiger"
print( "beroddeld" in s )