简体   繁体   English

递归函数中的Python生成器

[英]Python generator within a recursive function

I'm attempting to use a generator within a recursive statement, and I'm not getting the results I'm expecting. 我正在尝试在递归语句中使用生成器,但未获得预期的结果。

A little background: I'm working with syntax parse trees, and the conceptual goal is to recurse down the tree until I identify proper nouns (signified by the 'NNP' tag) and then I attempt to use a generator to identify every noun phrase (signified by the 'NP') that the proper noun is within. 一点背景知识:我正在使用语法分析树,并且概念上的目标是递归树直到找到合适的名词(由“ NNP”标记表示),然后尝试使用生成器来标识每个名词短语(由“ NP”表示)专有名词在其中。

alist = ['ROOT', ['S', ['NP', ['PRP', 'We']], ['VP', ['VBP', 'have'], ['VP', ['VBN', 'received'], ['NP', ['NN', 'information']],
        ['PP', ['IN', 'from'], ['NP', ['NP', ['DT', 'a'], ['NN', 'source']], ['VP', ['VBN', 'entitled'], ['PP', ['TO', 'to'],
        ['NP', ['NN', 'belief']]], [',', ','], ['SBAR', ['IN', 'that'], ['S', ['NP', ['NNP', 'Lincoln']], ['VP', ['VP', ['VBZ', 'has'],
        ['VP', ['VBN', 'paid'], ['NP', ['DT', 'a'], ['JJ', 'hurried'], ['NN', 'visit']], ['PP', ['TO', 'to'],
        ['NP', ['NP', ['DT', 'the'], ['NNP', 'Army']], ['PP', ['IN', 'of'], ['NP', ['DT', 'the'], ['NNP', 'Potomac']]]]],
        [',', ','], ['PRN', ['-LRB-', '-LRB-'], ['ADVP', ['RB', 'now']], ['ADJP', ['JJ', 'burrowing'], ['PP', ['IN', 'on'],
        ['NP', ['NP', ['DT', 'the'], ['NN', 'north'], ['NN', 'bank']], ['PP', ['IN', 'of'], ['NP', ['DT', 'the'], ['NNP', 'James']]],
        [',', ',']]]], ['-RRB-', '-RRB-']]]], ['CC', 'and'], ['VP', ['VBD', 'satisfied'], ['NP', ['PRP', 'himself']],
        [',', ','], ['PP', ['IN', 'by'], ['NP', ['JJ', 'personal'], ['NN', 'observation']]], [',', ','],
        ['PP', ['IN', 'in'], ['NP', ['NN', 'regard']]], ['PP', ['TO', 'to'], ['NP', ['NP', ['DT', 'the'], ['JJ', 'true'], ['NN', 'situation']],
        ['PP', ['IN', 'of'], ['NP', ['NNS', 'affairs']]]]]]]]]]]]]], ['.', '.']]]

def PullNP(NNP, NPLists):
    if NNP in NPLists:
        print "Pulling relevant NP"
        print NNP
        yield NNP
    for thing in NPLists:
        if NNP in thing:
            PullNP(thing, NPLists)
        else:
            for s in thing:
                if str(type(s)) == "<type 'list'>" and NNP in s: PullNP(s, NPLists)


def RecurseNNP(alist, pastlists=None, count=None):
    if pastlists is None: pastlists = []
    if count is None: count = 0
    if 'NNP' in alist[0]:
        NNPs = PullNP(alist, pastlists)
        print NNPs
        for np in NNPs:
            print np
    else:
        if str(type(alist)) == "<type 'list'>":
            if alist[0] == 'NP':
                pastlists.append(alist)
            for x in alist[1:]:
                RecurseNNP(x, pastlists, count)

RecurseNNP(alist)

If I run this code I get this output: 如果运行此代码,则会得到以下输出:

<generator object PullNP at 0x0288B648>
<generator object PullNP at 0x02885558>
<generator object PullNP at 0x02885558>
<generator object PullNP at 0x02885558>

And iterating through the generator objects yields no output. 遍历生成器对象不会产生任何输出。 However, if I remove the yield statement and merely run PullNP as a recursive function, I can confirm that the print statements contain what I want them to output. 但是,如果删除yield语句而仅将PullNP作为递归函数运行,则可以确认print语句包含我希望它们输出的内容。 ie I would like my generators to contain these lists: 即我希望我的生成器包含以下列表:

Pulling relevant NP
['NP', ['NNP', 'Lincoln']]
Pulling relevant NP
['NP', ['DT', 'the'], ['NNP', 'Army']]
Pulling relevant NP
['NP', ['NP', ['DT', 'the'], ['NNP', 'Army']], ['PP', ['IN', 'of'], ['NP', ['DT', 'the'], ['NNP', 'Potomac']]]]
Pulling relevant NP
['NP', ['DT', 'the'], ['NNP', 'Army']]
Pulling relevant NP
['NP', ['NP', ['DT', 'the'], ['NNP', 'Army']], ['PP', ['IN', 'of'], ['NP', ['DT', 'the'], ['NNP', 'Potomac']]]]
Pulling relevant NP
['NP', ['DT', 'the'], ['NNP', 'Potomac']]
Pulling relevant NP
['NP', ['NP', ['DT', 'the'], ['NNP', 'Army']], ['PP', ['IN', 'of'], ['NP', ['DT', 'the'], ['NNP', 'Potomac']]]]
Pulling relevant NP
['NP', ['DT', 'the'], ['NNP', 'James']]
Pulling relevant NP
['NP', ['NP', ['DT', 'the'], ['NN', 'north'], ['NN', 'bank']], ['PP', ['IN', 'of'], ['NP', ['DT', 'the'], ['NNP', 'James']]], [',', ',']]

I have read the major stack overflow posts explaining generators and yield, and I still don't understand why my generator is not outputting anything. 我已经阅读了主要的堆栈溢出文章,解释了生成器和良率,但我仍然不明白为什么生成器不输出任何内容。

Just calling sub-generator will not make the generator (iterator) run. 仅调用子生成器将不会使生成器(迭代器)运行。 You need to iterate the returned value (or explicitly call next on it) to run & consume yielded value. 您需要迭代返回的值(或显式调用next )以运行并使用产生的值。

This is recusive function. 这是回溯功能。 So yield the retrieved item back to caller. 因此,将检索到的项目交还给调用方。 Note the code part marked with # <--- 请注意标有# <---的代码部分

alist = ['ROOT', ['S', ['NP', ['PRP', 'We']], ['VP', ['VBP', 'have'], ['VP', ['VBN', 'received'], ['NP', ['NN', 'information']],
        ['PP', ['IN', 'from'], ['NP', ['NP', ['DT', 'a'], ['NN', 'source']], ['VP', ['VBN', 'entitled'], ['PP', ['TO', 'to'],
        ['NP', ['NN', 'belief']]], [',', ','], ['SBAR', ['IN', 'that'], ['S', ['NP', ['NNP', 'Lincoln']], ['VP', ['VP', ['VBZ', 'has'],
        ['VP', ['VBN', 'paid'], ['NP', ['DT', 'a'], ['JJ', 'hurried'], ['NN', 'visit']], ['PP', ['TO', 'to'],
        ['NP', ['NP', ['DT', 'the'], ['NNP', 'Army']], ['PP', ['IN', 'of'], ['NP', ['DT', 'the'], ['NNP', 'Potomac']]]]],
        [',', ','], ['PRN', ['-LRB-', '-LRB-'], ['ADVP', ['RB', 'now']], ['ADJP', ['JJ', 'burrowing'], ['PP', ['IN', 'on'],
        ['NP', ['NP', ['DT', 'the'], ['NN', 'north'], ['NN', 'bank']], ['PP', ['IN', 'of'], ['NP', ['DT', 'the'], ['NNP', 'James']]],
        [',', ',']]]], ['-RRB-', '-RRB-']]]], ['CC', 'and'], ['VP', ['VBD', 'satisfied'], ['NP', ['PRP', 'himself']],
        [',', ','], ['PP', ['IN', 'by'], ['NP', ['JJ', 'personal'], ['NN', 'observation']]], [',', ','],
        ['PP', ['IN', 'in'], ['NP', ['NN', 'regard']]], ['PP', ['TO', 'to'], ['NP', ['NP', ['DT', 'the'], ['JJ', 'true'], ['NN', 'situation']],
        ['PP', ['IN', 'of'], ['NP', ['NNS', 'affairs']]]]]]]]]]]]]], ['.', '.']]]

def PullNP(NNP, NPLists):
    if NNP in NPLists:
        print "Pulling relevant NP"
        print NNP
        yield NNP
    for thing in NPLists:
        if NNP in thing:
            for nnp in PullNP(thing, NPLists):
                yield nnp
        else:
            for s in thing:
                if isinstance(s, list) and NNP in s:
                    for nnp in PullNP(s, NPLists):  # <---
                        yield nnp                   # <---


def RecurseNNP(alist, pastlists=None, count=None):
    if pastlists is None: pastlists = []
    if count is None: count = 0
    if 'NNP' in alist[0]:
        NNPs = PullNP(alist, pastlists)
        print NNPs
        for np in NNPs:
            print np
    else:
        if str(type(alist)) == "<type 'list'>":
            if alist[0] == 'NP':
                pastlists.append(alist)
            for x in alist[1:]:
                RecurseNNP(x, pastlists, count)

RecurseNNP(alist)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM