2010-05-30 5 views
4

Je peux faire ce mal, si je le fais, faites le moi savoir, mais je suis curieux si ce qui suit est possible:Est-il possible de créer un itérateur python sur des données mutables prédéfinies?

J'ai une classe qui contient un certain nombre de dictionnaires, dont chacun des noms de paires à un ensemble différent d'objets d'une classe donnée. Par exemple:

items = {"ball" : ItemInstance1, "sword" : ItemInstance2} 
people = {"Jerry" : PersonInstance1, "Bob" : PersonInstance2, "Jill" : PersonInstance3} 

Ma classe convoquaient les éléments actuels et les gens qui sont macadamia, et ceux-ci seraient soumis à changer à mesure que les changements d'état:

Class State: 
    def __init__(self, items, people): 
     self.items = items 
     self.people = people 

Je voudrais définir une iter() et next() méthode telle qu'il itère à travers toutes les valeurs dans ses attributs. Ma première question est de savoir si c'est possible ou non. Si elle est, ce que ce sera en mesure de soutenir une situation comme suit:

Je définis les articles et les gens comme ci-dessus:

state = State(items, people) 
for names, thing in state: 
    print name + " is " + thing.color 

items[cheese] = ItemInstance3 
for names, thing in state: 
    print name + " weighs " + thing.weight 

Alors que je me sens comme cela serait utile dans le code que j'ai, je Je ne sais pas si c'est possible ou la bonne approche. Tout ce que j'ai lu sur les itérateurs définis par l'utilisateur a suggéré que chaque instance d'entre eux est à usage unique.

Répondre

2

Si je vous comprends correctement à la question, puis ajouter la méthode suivante à votre classe devrait le faire:

def __iter__(self): 
    import itertools 
    return itertools.chain(self.items.itervalues(), self.people.itervalues()) 

Cette chaîne ensemble deux itérateurs, et ceux choisis ici sont les valeurs de items et les valeurs de people. Pour faire fonctionner votre code plus tard, vous devrez parcourir les éléments - les paires clé-valeur. Dans ce cas, cela le ferait:

def __iter__(self): 
    import itertools 
    return itertools.chain(self.items.iteritems(), self.people.iteritems()) 
1

Il ya beaucoup de façons de faire ce que vous voulez. Vous pouvez en effet avoir une telle classe d'état et implémenter la méthode iter() (http://docs.python.org/library/stdtypes.html).

Vous pouvez également créer une fonction de générateur:

def iterate_two(l1, l2): 
     for k in l1: 
     yield k, l1[k] 
     for k in l2: 
     yield k, l2[k] 

Vous pouvez utiliser itertools.chain. Vous pouvez utiliser des listes de compréhension et des expressions de générateur. Etc.

Personnellement, je ne créerais pas la classe d'état comme vous le suggérez, si tout ce qu'il est est un mécanisme d'itérateur - j'utiliserais probablement une compréhension de liste.