Python:类:需要将我的列表变成生成器

时间:2018-03-08 17:54:35

标签: python function class generator

我已尝试在代码中实现“yield”,因此它将返回一个生成器,但它正在返回:

< 生成器对象PText.possible位于0x000001C9F4E03DB0 >

我基本上需要使用一个生成器,因为我使用的txt文件非常长并且创建列表需要一段时间并且速度很慢,所以我需要以某种方式实现一个生成器以使其不会占用尽可能多的时间。

我使用return语句编写了所有代码,并尝试插入yield但是它不起作用。我错过了什么吗?我相信在代码中有两个实例需要生成器,但我无法弄明白。

这是一个连续的代码,我标记了我使用yield的地方:

WORD_LIST_FILE = 'English_words_by_usage_rank.txt'
# this is just a file with a list of words

class PText(object):
    keyMap = {'1': "'-", '2': 'abc', '3': 'def',
              '4': 'ghi', '5': 'jkl', '6': 'mno',
              '7': 'pqrs', '8': 'tuv', '9': 'wxyz'}
    wordsByPrefix = None
    rankByWord = None

    def __init__(self):
        self.keys = []

    def add(self, keys_typed):
        """ Append a new key press (or a sequence of them) onto current word.
        keyPress -- '2', '3', ..., '9' from telephone keypad.
        >>> pt= Ptext()
        >>> pt.add('345')
        >>> pt.keys
        ['3', '4', '5']
        """
        for key in  keys_typed:
            if key in PText.keyMap:
                self.keys.append(key)

    def backspace(self):
        """Remove last key press from current word (backspace)."""
        if len(self.keys) > 0:
            self.keys.pop()

    def match(self, word):
        """See if word might be what the phone user is trying to type."""
        if len(word) < len(self.keys):
            return False
        for i in range(len(self.keys)):
            letter = word[i]
            keystroke = self.keys[i]
            ok_letters = PText.keyMap[keystroke]
            if letter not in ok_letters:
                return False
        # if all the keys matched the corrresponding letters in word
        return True

我在这部分中使用了屈服:

    def possiblePrefixes(self):
        """ Generate a list of all 3-char prefixes that can be gernerated
        from the beginning key presses.
        """
        if len(self.keys) < 3:
            raise ValueError("not enough keys for prefixes")
        ret = []
        kmap = PText.keyMap
        for c1 in kmap[self.keys[0]]:
            for c2 in kmap[self.keys[1]]:
                for c3 in kmap[self.keys[2]]:
                    ret.append(c1 + c2 + c3)
        yield ret

    def _performCaching(self):
        """Read word list into data structures that we will use:

        wordsByPrefix -- a dictionary that contains a list of words in rank
                         order for each 3-letter prefix encountered in the
                         word list

        rankByWord -- a dictionary that maps each word to its rank

        If these are already filled in (not None), then return immediately.

        Reads the word list file, WORD_LIST_FILE, which has all possible
        English words (that we will consider) listed in rank order.
        """
        if PText.wordsByPrefix is not None:
            return
        wbp = {}
        rbw = {}
        rank = 1
        file = open(WORD_LIST_FILE, 'r')
        for word in file:
            if word[-1:] == '\n':
                word = word[:-1]
            #print("'" + word + "'")
            if len(word) >= 3:
                prefix = word[:3].lower()
                if prefix in wbp:
                    wbp[prefix].append(word)
                else:
                    wbp[prefix] = [word]
                rbw[word] = rank
                rank += 1
        file.close()

        PText.wordsByPrefix = wbp
        PText.rankByWord = rbw

这里的另一个收益:

    def possible(self):
        """Returns a list of possible words given the current key sequence.
        Assumes at least 3 keystrokes have been entered (raises ValueError
        otherwise). Returned in rank order.
        """
        self._performCaching()
        if len(self.keys) < 3:
            raise ValueError('Too few keys for predicting word')
        wbp = PText.wordsByPrefix
        ret = []
        for prefix in self.possiblePrefixes():
            if prefix in wbp:
                wordList = wbp[prefix]
                for word in wordList:
                    if self.match(word):
                        ret.append(word)
        ret1 = []
        [ret1.append(item) for item in ret if item not in ret1]
        yield ret1


    def best(self):
        """Return the most likely English word for the current key sequence.
        Assumes at least 3 keystrokes have been entered (raises ValueError
        otherwise). If there a no words that match the current key sequence,
        ValueError is raised.
        """
        rank = 1
        highest = 1
        ranking = {}
        for prefix in self.possible():
            ranking[prefix] = rank
            rank += 1
        for vals in ranking.values():
            if vals == highest:
                highest = vals
        bests = ([k for k,v in ranking.items() if v == highest])
        for i in bests:
            answer = i
        return i

2 个答案:

答案 0 :(得分:3)

您对发电机的理解和使用是不正确的。以下是您目前正在尝试执行的操作的简化示例:

def possiblePrefixes():
    ret = []
    keys = ['abc','def','ghi']
    for c1 in keys[0]:
        for c2 in keys[1]:
            for c3 in keys[2]:
                ret.append(c1 + c2 + c3)
    yield ret

print(possiblePrefixes())

输出:

<generator object possiblePrefixes at 0x000001DCFFCE99E8>

这通常是打印发电机返回值时得到的结果。你使用生成器做什么是迭代,但逻辑是有缺陷的。您已在列表中生成所有答案,并生成一个大列表。这违背了发电机的目的:

for p in possiblePrefixes():
    print(p)

输出:

['adg', 'adh', 'adi', 'aeg', 'aeh', 'aei', 'afg', 'afh', 'afi', 'bdg', 'bdh', 'bdi', 'beg', 'beh', 'bei', 'bfg', 'bfh', 'bfi', 'cdg', 'cdh', 'cdi', 'ceg', 'ceh', 'cei', 'cfg', 'cfh', 'cfi']

生成器应该一次生成一个值。它不会预先生成所有值:

def possiblePrefixesFixed():
    ret = []
    keys = ['abc','def','ghi']
    for c1 in keys[0]:
        for c2 in keys[1]:
            for c3 in keys[2]:
                yield c1 + c2 + c3

print(possiblePrefixesFixed())

for p in possiblePrefixesFixed():
    print(p)

输出:

<generator object possiblePrefixesFixed at 0x000001DCFFCE99E8>
adg
adh
adi
aeg
aeh
aei
afg
afh
afi
bdg
bdh
bdi
beg
beh
bei
bfg
bfh
bfi
cdg
cdh
cdi
ceg
ceh
cei
cfg
cfh
cfi

答案 1 :(得分:0)

您似乎对yield的工作方式感到有些困惑。

一个例子是

def square_gen_fun(seq):
    for i in seq:
        yield x

我要返回一个生成器对象。要访问此生成器的结果,我可以像这样迭代它:

gen = square_gen_fun(range(5))
for i2 in gen:
     print(i2, end=' ')

将打印出0 1 4 9 16

你在这里做什么

ret = []
for c1 in kmap[self.keys[0]]:
    for c2 in kmap[self.keys[1]]:
        for c3 in kmap[self.keys[2]]:
            ret.append(c1 + c2 + c3)
yield ret

错了。您将返回一个生成器对象,该对象具有一个元素,一个列表或c1+c2+c3元素。你真正想要的是:

for c1 in kmap[self.keys[0]]:
    for c2 in kmap[self.keys[1]]:
        for c3 in kmap[self.keys[2]]:
            yield c1 + c2 + c3