Доступ к локальным переменным внутри генератора Python - PullRequest
6 голосов
/ 19 января 2011

Как вы получите доступ к локальной переменной, определенной внутри генератора Python, из-за пределов генератора?

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

Я не могу сохранить состояние в переменной экземпляра (например, self.state = blah), поскольку я могу создавать несколько генераторов из одного экземпляра класса, то есть генераторы могут перезаписывать состояние друг друга.Я также не могу вернуть состояние в выражении yield, потому что имя состояния может меняться или изменяться из-за отдельных экземпляров генератора.

например, я хочу сделать что-то подобное (хотя этот код не работает)

from random import random

class MyIter(object):
    def __iter__(self):
        context = {}
        for i in xrange(10):
            context[random()] = random()
            yield i

obj = MyIter()
i1 = iter(obj)
i2 = iter(obj)
while 1:
    try:
        i1.next()
        i2.next()
        print i1.context
        print i2.context
    except StopIteration:
        break

Есть ли в любом случае доступ к локальным переменным путем проверки стека выполнения Python?

Ответы [ 3 ]

4 голосов
/ 19 января 2011

Извините, что отвечаю на мой собственный вопрос, но после поиска в интерфейсе генератора я нашел точный путь, который мне нужен для доступа к локальным переменным генератора:

from random import random

class MyIter(object):
    def __iter__(self):
        context = {}
        for i in xrange(10):
            context[random()] = random()
            yield i

obj = MyIter()
i1 = iter(obj)
i2 = iter(obj)
while 1:
    try:
        i1.next()
        i2.next()
        print i1.gi_frame.f_locals['context']
        print i2.gi_frame.f_locals['context']
    except StopIteration:
        break
0 голосов
/ 19 января 2011

Если вы действительно хотите это сделать, отделите класс итератора от класса контейнера:

from random import random

class MyContainer(object):
    def __iter__(self):
        return MyIter(self)

class MyIter(object):
    def __init__(self, container):
        self.container = container
        self.context = {}
        self.it = iter(xrange(10))
    def next(self):
        self.context[random()] = random()
        return next(self.it)
    def __iter__(self):
        return self

obj = MyContainer()
# ...

Хотя я не считаю это очень полезным ...

0 голосов
/ 19 января 2011

Вы должны относиться к генератору как к черному ящику.Модульные тесты не должны заботиться о его внутреннем состоянии, потому что это всего лишь деталь реализации;они должны заботиться только об указанном поведении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...