Python - поддержка .send () для класса? - PullRequest
7 голосов
/ 14 декабря 2010

Написание класса, как мне реализовать

foo.send (item)?

__iter__ позволяет перебирать класс как генератор, что если я хочу, чтобы он был сопрограммой?

1 Ответ

7 голосов
/ 14 декабря 2010

Вот базовый пример сопрограммы :

def coroutine(func):
    def start(*args,**kwargs):
        cr = func(*args,**kwargs)
        cr.next()
        return cr
    return start

@coroutine
def grep(pattern):
    print "Looking for %s" % pattern
    while True:
        line = (yield)
        if pattern in line:
            print(line)

g = grep("python")
# Notice how you don't need a next() call here
g.send("Yeah, but no, but yeah, but no")
g.send("A series of tubes")
g.send("python generators rock!")
# Looking for python
# python generators rock!

Мы можем создать класс, который содержит такую ​​сопрограмму и делегирует вызовы его send метода сопрограмме:

class Foo(object):
    def __init__(self,pattern):
        self.count=1
        self.pattern=pattern
        self.grep=self._grep()
    @coroutine
    def _grep(self):
        while True:
            line = (yield)
            if self.pattern in line:
                print(self.count, line)
                self.count+=1
    def send(self,arg):
        self.grep.send(arg)

foo = Foo("python")
foo.send("Yeah, but no, but yeah, but no")
foo.send("A series of tubes")
foo.send("python generators rock!")
foo.pattern='spam'
foo.send("Some cheese?")
foo.send("More spam?")

# (1, 'python generators rock!')
# (2, 'More spam?')

Обратите внимание, что foo действует как сопрограмма (поскольку он имеет метод send), но является классом - он может иметь атрибуты и методы, которые могут взаимодействовать с сопрограммой.

Для получения дополнительной информации (и замечательных примеров), см. Любопытный курс Дэвида Бизли по сопрограммам и параллелизму.

...