2010-05-30 2 views
4

я мог бы делать это неправильно, если я, дайте мне знать, но мне интересно, если возможно следующее:Возможно ли создать итератор python над предопределенными изменяемыми данными?

У меня есть класс, который содержит ряд словарей, каждый из которых пар имен в другой набор объектов данного класса. Например:

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

Мой класс будет тогда держать текущие предметы и людей, которые воевавших, и это будет изменяться по мере изменения состояний:

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

Я хотел бы определить iter() и next(), так что он выполняет итерацию по всем значениям в своих атрибутах. Мой первый вопрос заключается в том, возможно ли это. Если да, то он будет в состоянии поддерживать ситуацию следующим образом:

Я определяю предметы и людей, как описано выше, а затем:

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 

В то время как я чувствую, что это было бы полезно в коде у меня есть, я не знаю, возможно ли это или правильный подход. Все, что я прочитал об итераторах, определенных пользователем, предположил, что каждый их экземпляр используется только один.

ответ

2

Если я понимаю вас вопрос правильно, то добавить следующий метод в классе должен это сделать:

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

This цепи вместе два итератора, и те, выбранные здесь для значений items и значений people.

Чтобы сделать ваш более поздний код работать, вам нужно будет перебирать элементы - пары ключ-значение. В этом случае это сделало бы это:

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

Существует множество способов сделать то, что вы хотите. Вы действительно можете иметь такой класс состояний и реализовать метод iter() (http://docs.python.org/library/stdtypes.html).

Вы также можете создать функцию генератора:

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

Вы можете использовать itertools.chain. Вы можете использовать выражения списков и выражения генератора. И т. Д.

Я лично не создавал бы класс State, как вы предлагаете, если все это механизм итератора - я бы, вероятно, использовал понимание списка.

Смежные вопросы