在Python3中将对象转换为迭代器?

2024-09-27 23:15:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将一个库移植到python3。它有一个用于PDF流的标记器。reader类对这些标记调用next()。这在python2中是有效的,但是当我在python3中运行它时,我得到了TypeError: 'PdfTokens' object is not an iterator。你知道吗

关于迭代器的tokens.py选择:

class PdfTokens(object):
    def __init__(self, fdata, startloc=0, strip_comments=True):
        self.fdata = fdata
        self.iterator = iterator = self._gettoks(startloc)
        self.next = next(iterator)

    def __iter__(self):
        return self.iterator

    def _gettoks(self, startloc, cacheobj=_cacheobj,
                       delimiters=delimiters, findtok=findtok, findparen=findparen,
                       PdfString=PdfString, PdfObject=PdfObject):
        fdata = self.fdata
        current = self.current = [(startloc, startloc)]
        namehandler = (cacheobj, self.fixname)
        cache = {}
        while 1:
            for match in findtok(fdata, current[0][1]):
                current[0] = tokspan = match.span()
                token = match.group(1)
                firstch = token[0]
                if firstch not in delimiters:
                    token = cacheobj(cache, token, PdfObject)
                elif firstch in '/<(%':
                    if firstch == '/':
                        # PDF Name
                        token = namehandler['#' in token](cache, token, PdfObject)
                    elif firstch == '<':
                        # << dict delim, or < hex string >
                        if token[1:2] != '<':
                            token = cacheobj(cache, token, PdfString)
                    elif firstch == '(':
                        ends = None  # For broken strings
                        if fdata[match.end(1)-1] != ')':
                            nest = 2
                            m_start, loc = tokspan
                            for match in findparen(fdata, loc):
                                loc = match.end(1)
                                ending = fdata[loc-1] == ')'
                                nest += 1 - ending * 2
                                if not nest:
                                    break
                                if ending and ends is None:
                                    ends = loc, match.end(), nest
                            token = fdata[m_start:loc]
                            current[0] = m_start, match.end()
                            if nest:
                                (self.error, self.exception)[not ends]('Unterminated literal string')
                                loc, ends, nest = ends
                                token = fdata[m_start:loc] + ')' * nest
                                current[0] = m_start, ends
                        token = cacheobj(cache, token, PdfString)
                    elif firstch == '%':
                        # Comment
                        if self.strip_comments:
                            continue
                    else:
                        self.exception('Tokenizer logic incorrect -- should never get here')

                yield token
                if current[0] is not tokspan:
                    break
            else:
                if self.strip_comments:
                    break
                raise StopIteration

pdfreader文件中引发错误的有问题方法的开头:

def findxref(fdata):
    ''' Find the cross reference section at the end of a file
    '''
    startloc = fdata.rfind('startxref')
    if startloc < 0:
        raise PdfParseError('Did not find "startxref" at end of file')
    source = PdfTokens(fdata, startloc, False)
    tok = next(source)

我的印象是,定义自定义迭代器对象所需的只是.__iter__方法和.next()方法,并引发StopIteration错误。这个类拥有所有这些东西,但仍然会引发类型错误。你知道吗

此外,这个库及其方法在Python2.7中工作,并且已经停止在Python3环境中工作。那么python3又有什么不同呢?如何使PdfTokens对象可编辑?你知道吗


Tags: selftokenifmatchnotcurrentlocnext
1条回答
网友
1楼 · 发布于 2024-09-27 23:15:55

不能直接调用PdfTokens实例上的next,需要先通过调用iter()来获取其迭代器。这也正是for循环所做的*,它首先调用对象上的iter(),然后得到一个迭代器,然后在循环中,在该迭代器上调用__next__,直到它没有用尽:

instance = PdfTokens(fdata, startloc, False)
source = iter(instance)
tok = next(source)

也不总是这样,如果类上没有定义__iter__,那么迭代器协议会返回到__getitem__,如果定义的话。

相关问题 更多 >

    热门问题