Используя предвидение с генераторами

Насколько я знаю, единственный способ сделать отслеживание стека доступным для Вашего собственного кода через getStackTrace () метод в Ошибочном классе, точно так же, как Вы уже делаете. В ответ на пример в Вашем вопросе, тем не менее, я упомянул бы, что Вы не должны на самом деле бросать Ошибку - можно просто создать его и назвать метод на нем:

var tempError:Error = new Error();
var stackTrace:String = tempError.getStackTrace();

кроме того, как документация говорит, это только работает в отладочной версии Flash player, таким образом, можно обернуть эту функциональность в если-блок, который проверяет значение Capabilities.isDebugger, если Вы хотите.

18
задан jena 23 August 2013 в 23:31
поделиться

6 ответов

Вы можете написать оболочку, которая буферизует некоторое количество элементов из генератора и предоставляет функцию lookahead () для просмотра этих буферизованных элементов:

class Lookahead:
    def __init__(self, iter):
        self.iter = iter
        self.buffer = []

    def __iter__(self):
        return self

    def next(self):
        if self.buffer:
            return self.buffer.pop(0)
        else:
            return self.iter.next()

    def lookahead(self, n):
        """Return an item n entries ahead in the iteration."""
        while n >= len(self.buffer):
            try:
                self.buffer.append(self.iter.next())
            except StopIteration:
                return None
        return self.buffer[n]
14
ответ дан 30 November 2019 в 06:35
поделиться

Там довольно хорошие ответы, но я предпочитаю использовать itertools.tee - с учетом итератора он возвращает два ( или больше, если требуется), которые могут быть расширены независимо. Он буферизует в памяти столько, сколько необходимо (т.е. если итераторы не слишком "расходятся" друг с другом). Например:

import itertools
import collections

class IteratorWithLookahead(collections.Iterator):
  def __init__(self, it):
    self.it, self.nextit = itertools.tee(iter(it))
    self._advance()
  def _advance(self):
    self.lookahead = next(self.nextit, None)
  def __next__(self):
    self._advance()
    return next(self.it)

Вы можете обернуть любой итератор этим классом, а затем использовать атрибут .lookahead оболочки, чтобы узнать, какой следующий элемент будет возвращен в будущем. Мне нравится оставлять всю реальную логику itertools.tee и просто предоставлять этот тонкий клей! -)

22
ответ дан 30 November 2019 в 06:35
поделиться

Это некрасиво, но это может делать то, что вы хотите:

def paired_iter(it):
    token = it.next()
    for lookahead in it:
        yield (token, lookahead)
        token = lookahead
    yield (token, None)

def scan(s):
    for c in s:
        yield c

for this_token, next_token in paired_iter(scan("ABCDEF")):
    print "this:%s next:%s" % (this_token, next_token)

Печать:

this:A next:B
this:B next:C
this:C next:D
this:D next:E
this:E next:F
this:F next:None
6
ответ дан 30 November 2019 в 06:35
поделиться

Поскольку вы говорите, что токенизируете строку, а не общую итерацию, я предлагаю простейшее решение - просто расширить ваш токенизатор, чтобы вернуть 3-кортеж: (token_type, token_value, token_index) , где token_index - это индекс токена в строке. Затем вы можете смотреть вперед, назад или в любое другое место в строке. Только не уходи до конца. Я думаю, что это самое простое и гибкое решение.

Кроме того, вам не нужно использовать понимание списка для создания списка из генератора. Просто вызовите на нем конструктор list ():

 token_list = list(scan(string))
1
ответ дан 30 November 2019 в 06:35
поделиться

Вот пример, который позволяет отправить один элемент обратно в генератор

def gen():
    for i in range(100):
        v=yield i           # when you call next(), v will be set to None
        if v:
            yield None      # this yields None to send() call
            v=yield v       # so this yield is for the first next() after send()

g=gen()

x=g.next()
print 0,x

x=g.next()
print 1,x

x=g.next()
print 2,x # oops push it back

x=g.send(x)

x=g.next()
print 3,x # x should be 2 again

x=g.next()
print 4,x
3
ответ дан 30 November 2019 в 06:35
поделиться

Павел - хороший ответ. Подход на основе классов с произвольным опережением может выглядеть примерно так:

class lookahead(object):
    def __init__(self, generator, lookahead_count=1):
        self.gen = iter(generator)
        self.look_count = lookahead_count

    def __iter__(self):
        self.lookahead = []
        self.stopped = False
        try:
            for i in range(self.look_count):
                self.lookahead.append(self.gen.next())
        except StopIteration:
            self.stopped = True
        return self

    def next(self):
        if not self.stopped:
            try:
                self.lookahead.append(self.gen.next())
            except StopIteration:
                self.stopped = True
        if self.lookahead != []:
            return self.lookahead.pop(0)
        else:
            raise StopIteration

x = lookahead("abcdef", 3)
for i in x:
    print i, x.lookahead
0
ответ дан 30 November 2019 в 06:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: